//------------------------------------------------- // Litchi Game Server Framework // Copyright(c) 2019 phantaci <[email protected]> // MIT Licensed //------------------------------------------------- package litchi.core.common.utils; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ThreadLocalRandom; /** * 集合工具类 * @author 0x737263 * */ public abstract class CollectionUtils { /** * 连续复制一段集合对象 * @param source 数据源集合 * @param start 开始索引 * @param count 复制总记录数 * @return */ public static <T> List<T> subListCopy(List<T> source, int start, int count) { if ((source == null) || (source.size() == 0)) { return new ArrayList<T>(0); } int fromIndex = (start <= 0) ? 0 : start; if (start > source.size()) { fromIndex = source.size(); } count = (count <= 0) ? 0 : count; int endIndex = fromIndex + count; if (endIndex > source.size()) { endIndex = source.size(); } return new ArrayList<T>(source.subList(fromIndex, endIndex)); } @SafeVarargs public static <T> List<T> asList(T ...items) { List<T> list = new ArrayList<T>(); if (items != null) { for (T item : items) { list.add(item); } } return list; } public static <T,S> Map<T,S> asMap(T key, S val) { Map<T, S> map = new HashMap<T, S>(); map.put(key, val); return map; } /** * 截取分页集合 * @param list 集合 * @param startIndex 索引 * @param fetchCount 获取总数 * @return */ public static <T> List<T> pageResult(List<T> list, int startIndex, int fetchCount) { if ((list != null) && (list.size() > 0)) { if (startIndex >= list.size()) { return null; } startIndex = (startIndex < 0) ? 0 : startIndex; if (fetchCount <= 0) { return list.subList(startIndex, list.size()); } int toIndex = Math.min(startIndex + fetchCount, list.size()); return list.subList(startIndex, toIndex); } return null; } /** * 判断集合是否有元素 * @param c * @return */ public static <T> boolean isEmpty(Collection<T> c) { return c == null || c.size() == 0; } /** * 判断集合是否有元素 * @param c * @return */ public static <T> boolean isNotEmpty(Collection<T> c) { return c != null && c.size() > 0; } /** * 判断字典是否有元素 * @param c * @return */ public static <K,V> boolean isEmpty(Map<K,V> c) { return c == null || c.size() == 0; } /** * 判断字典是否有元素 * @param c * @return */ public static <K,V> boolean isNotEmpty(Map<K,V> c) { return c != null && c.size() > 0; } /** * 将collection2中的元素从collection1中移除 * @param collection1 * @param collection2 */ public static <T> void detainAll(Collection<T> collection1, Collection<T> collection2) { if (isEmpty(collection1) || isEmpty(collection2)) { return; } Set<T> set = new HashSet<T>(); set.addAll(collection2); Iterator<T> iter = collection1.iterator(); while(iter.hasNext()) { if (set.contains(iter.next())) { iter.remove(); } } } public static <K,V> void detainAll(Map<K, V> map, Set<K> exclutions) { if (isEmpty(exclutions) || isEmpty(exclutions)) { return; } for (K key : exclutions) { map.remove(key); } } /** * 判断两个集合的内容是否是一样的(顺序不一定相同) * @param collection1 * @param collection2 * @return */ public static <T> boolean isSame(Collection<T> collection1, Collection<T> collection2) { Set<T> set1 = new HashSet<>(); Set<T> set2 = new HashSet<>(); set1.addAll(collection1); set2.addAll(collection2); for (T t : collection1) { if (!set2.contains(t)) { return false; } } for (T t : collection2) { if (!set1.contains(t)) { return false; } } return true; } public static <T> boolean isNotSame(Collection<T> collection1, Collection<T> collection2) { return isSame(collection1, collection2) == false; } //===========dx /** * 获取集合页数 * @param list * @param pageSement * @return */ public static <T> int findPages(List<T> list, int pageSement) { int pages = list.size() / pageSement; return list.size() % pageSement == 0 ? pages : pages + 1; } /** * 获取第X页 * @param list * @param page * @return */ public static <T> Collection<T> getPages(List<T> list, int page, int pageSement) { Collection<T> pages = new ArrayList<>(); Page p = Page.valueOf(page, pageSement); int start = (int) (p.getStart() - 1); int end = (int) (p.getEnd()); int indexLimit = list.size() - 1; for (int i = start; i < end; i++) { if (i > indexLimit) { break; } T t = list.get(i); if (t == null) { break; } else { pages.add(t); } } return pages; } public static class Page { private int page; private long start; private long end; public Page(int page, long start, long end) { this.page = page; this.start = start; this.end = end; } public boolean inPage(long value) { return value >= start && page <= end; } public static int findPage(long value, int segment) { if (value % segment == 0) { return (int) (value / segment); } return (int) (value / segment + 1); } private static final int DEFAULT_SEGMENT = 50; private static ConcurrentHashMap<Integer, ConcurrentHashMap<Integer, Page>> cache = new ConcurrentHashMap<>(); static { ConcurrentHashMap<Integer, Page> pages = new ConcurrentHashMap<>(); for (int i = 1; i <= 10; i++) { int start = (i - 1) * DEFAULT_SEGMENT + 1; long end = i * DEFAULT_SEGMENT; pages.put(i, new Page(i, start, end)); } cache.put(DEFAULT_SEGMENT, pages); } public static List<Page> findBetweenPages(long from, long to, int segment) { List<Page> pages = new ArrayList<>(); int fromPage = findPage(from, segment); int toPage = findPage(to, segment); for (int i = 0, l = fromPage - toPage; i < l; i++) { pages.add(valueOf(fromPage - i, segment)); } return pages; } public static Page valueOf(int page, int segment) { ConcurrentHashMap<Integer, Page> pages = cache.get(segment); if (pages == null) { pages = new ConcurrentHashMap<>(); cache.put(segment, pages); } Page p = pages.get(page); if (p == null) { int start = (page - 1) * segment + 1; long end = page * segment; p = new Page(page, start, end); pages.put(page, p); } return p; } public int getPage() { return page; } public void setPage(int page) { this.page = page; } public long getStart() { return start; } public void setStart(long start) { this.start = start; } public long getEnd() { return end; } public void setEnd(long end) { this.end = end; } } public static <T> List<T> random(List<T> collection, int num) { if (collection.size() == 0) { return null; } List<T> list = new ArrayList<>(); if (collection.isEmpty()) { return list; } if (num >= collection.size()) { list.addAll(collection); return list; } for (int i = 0; i < 1000; i++) { int r = ThreadLocalRandom.current().nextInt(0, collection.size()); T obj = collection.get(r); if (list.contains(obj)) { continue; } list.add(obj); num--; if (num <= 0) { break; } } return list; } public static <T> T random(Collection<T> collection) { if (collection.size() == 0) { return null; } int r = ThreadLocalRandom.current().nextInt(0, collection.size()); int index = 0; for (T t : collection) { if (index == r) { return t; } index++; } return null; } }