From 8c9abbe3e3367bc05d6bb5305c0361474b00a6b3 Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 25 Mar 2020 17:49:25 +0800 Subject: [PATCH] add ListUtil --- CHANGELOG.md | 2 + .../cn/hutool/core/collection/CollUtil.java | 235 +++------ .../cn/hutool/core/collection/ListUtil.java | 448 ++++++++++++++++++ .../cn/hutool/core/lang/ConsistentHash.java | 22 +- .../cn/hutool/core/lang/hash/Hash128.java | 19 + .../java/cn/hutool/core/lang/hash/Hash32.java | 19 + .../java/cn/hutool/core/lang/hash/Hash64.java | 19 + .../hutool/core/collection/CollUtilTest.java | 12 +- 8 files changed, 591 insertions(+), 185 deletions(-) create mode 100644 hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java create mode 100644 hutool-core/src/main/java/cn/hutool/core/lang/hash/Hash128.java create mode 100644 hutool-core/src/main/java/cn/hutool/core/lang/hash/Hash32.java create mode 100644 hutool-core/src/main/java/cn/hutool/core/lang/hash/Hash64.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 7eb73584a..40f68cdee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ * 【cache 】 修改FIFOCache中linkedHashMap的初始容量策略(pr#801@Github) * 【core 】 修改XmlUtil中setNamespaceAware默认为true * 【core 】 TreeNode增加extra +* 【core 】 CollUtil.newHashSet重载歧义,更换为set方法 +* 【core 】 增加ListUtil,增加Hash32、Hash64、Hash128接口 ### Bug修复 * 【core 】 修复NumberWordFormatter拼写错误(issue#799@Github) diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java b/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java index 2277d8cf1..0f116f6a2 100644 --- a/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java @@ -9,12 +9,12 @@ import cn.hutool.core.exceptions.UtilException; import cn.hutool.core.lang.Editor; import cn.hutool.core.lang.Filter; import cn.hutool.core.lang.Matcher; +import cn.hutool.core.lang.hash.Hash32; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.CharUtil; import cn.hutool.core.util.ClassUtil; import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.PageUtil; import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.TypeUtil; @@ -199,8 +199,13 @@ public class CollUtil { /** * 两个集合的差集
* 针对一个集合中存在多个相同元素的情况,计算两个集合中此元素的个数,保留两个集合中此元素个数差的个数
- * 例如:集合1:[a, b, c, c, c],集合2:[a, b, c, c]
- * 结果:[c],此结果中只保留了一个
+ * 例如: + * + *
+	 *     disjunction([a, b, c, c, c], [a, b, c, c]) -》 [c]
+	 *     disjunction([a, b], [])                    -》 [a, b]
+	 *     disjunction([a, b, c], [b, c, d])          -》 [a, d]
+	 * 
* 任意一个集合为空,返回另一个集合
* 两个集合无差集则返回空集合 * @@ -232,6 +237,24 @@ public class CollUtil { return result; } + /** + * 计算集合的单差集,即只返回【集合1】中有,但是【集合2】中没有的元素,例如: + * + *
+	 *     subtract([1,2,3,4],[2,3,4,5]) -》 [1]
+	 * 
+ * + * @param coll1 集合1 + * @param coll2 集合2 + * @param 元素类型 + * @return 单差集 + */ + public static Collection subtract(Collection coll1, Collection coll2) { + final Collection result = ObjectUtil.clone(coll1); + result.removeAll(coll2); + return result; + } + /** * 判断指定集合是否包含指定值,如果集合为空(null或者空),返回{@code false},否则找到元素返回{@code true} * @@ -450,7 +473,7 @@ public class CollUtil { */ @SafeVarargs public static HashSet newHashSet(T... ts) { - return newHashSet(false, ts); + return set(false, ts); } /** @@ -475,7 +498,7 @@ public class CollUtil { * @return HashSet对象 */ @SafeVarargs - public static HashSet newHashSet(boolean isSorted, T... ts) { + public static HashSet set(boolean isSorted, T... ts) { if (null == ts) { return isSorted ? new LinkedHashSet<>() : new HashSet<>(); } @@ -519,7 +542,7 @@ public class CollUtil { */ public static HashSet newHashSet(boolean isSorted, Iterator iter) { if (null == iter) { - return newHashSet(isSorted, (T[]) null); + return set(isSorted, (T[]) null); } final HashSet set = isSorted ? new LinkedHashSet<>() : new HashSet<>(); while (iter.hasNext()) { @@ -539,7 +562,7 @@ public class CollUtil { */ public static HashSet newHashSet(boolean isSorted, Enumeration enumeration) { if (null == enumeration) { - return newHashSet(isSorted, (T[]) null); + return set(isSorted, (T[]) null); } final HashSet set = isSorted ? new LinkedHashSet<>() : new HashSet<>(); while (enumeration.hasMoreElements()) { @@ -559,7 +582,7 @@ public class CollUtil { * @since 4.1.2 */ public static List list(boolean isLinked) { - return isLinked ? new LinkedList<>() : new ArrayList<>(); + return ListUtil.list(isLinked); } /** @@ -573,12 +596,7 @@ public class CollUtil { */ @SafeVarargs public static List list(boolean isLinked, T... values) { - if (ArrayUtil.isEmpty(values)) { - return list(isLinked); - } - final List arrayList = isLinked ? new LinkedList<>() : new ArrayList<>(values.length); - Collections.addAll(arrayList, values); - return arrayList; + return ListUtil.list(isLinked, values); } /** @@ -591,10 +609,7 @@ public class CollUtil { * @since 4.1.2 */ public static List list(boolean isLinked, Collection collection) { - if (null == collection) { - return list(isLinked); - } - return isLinked ? new LinkedList<>(collection) : new ArrayList<>(collection); + return ListUtil.list(isLinked, collection); } /** @@ -608,10 +623,7 @@ public class CollUtil { * @since 4.1.2 */ public static List list(boolean isLinked, Iterable iterable) { - if (null == iterable) { - return list(isLinked); - } - return list(isLinked, iterable.iterator()); + return ListUtil.list(isLinked, iterable); } /** @@ -625,13 +637,7 @@ public class CollUtil { * @since 4.1.2 */ public static List list(boolean isLinked, Iterator iter) { - final List list = list(isLinked); - if (null != iter) { - while (iter.hasNext()) { - list.add(iter.next()); - } - } - return list; + return ListUtil.list(isLinked, iter); } /** @@ -640,18 +646,12 @@ public class CollUtil { * * @param 集合元素类型 * @param isLinked 是否新建LinkedList - * @param enumration {@link Enumeration} + * @param enumeration {@link Enumeration} * @return ArrayList对象 * @since 3.0.8 */ - public static List list(boolean isLinked, Enumeration enumration) { - final List list = list(isLinked); - if (null != enumration) { - while (enumration.hasMoreElements()) { - list.add(enumration.nextElement()); - } - } - return list; + public static List list(boolean isLinked, Enumeration enumeration) { + return ListUtil.list(isLinked, enumeration); } /** @@ -660,10 +660,11 @@ public class CollUtil { * @param 集合元素类型 * @param values 数组 * @return ArrayList对象 + * @see #toList(Object[]) */ @SafeVarargs public static ArrayList newArrayList(T... values) { - return (ArrayList) list(false, values); + return ListUtil.toList(values); } /** @@ -676,7 +677,7 @@ public class CollUtil { */ @SafeVarargs public static ArrayList toList(T... values) { - return newArrayList(values); + return ListUtil.toList(values); } /** @@ -687,7 +688,7 @@ public class CollUtil { * @return ArrayList对象 */ public static ArrayList newArrayList(Collection collection) { - return (ArrayList) list(false, collection); + return ListUtil.toList(collection); } /** @@ -700,7 +701,7 @@ public class CollUtil { * @since 3.1.0 */ public static ArrayList newArrayList(Iterable iterable) { - return (ArrayList) list(false, iterable); + return ListUtil.toList(iterable); } /** @@ -708,12 +709,12 @@ public class CollUtil { * 提供的参数为null时返回空{@link ArrayList} * * @param 集合元素类型 - * @param iter {@link Iterator} + * @param iterator {@link Iterator} * @return ArrayList对象 * @since 3.0.8 */ - public static ArrayList newArrayList(Iterator iter) { - return (ArrayList) list(false, iter); + public static ArrayList newArrayList(Iterator iterator) { + return ListUtil.toList(iterator); } /** @@ -721,12 +722,12 @@ public class CollUtil { * 提供的参数为null时返回空{@link ArrayList} * * @param 集合元素类型 - * @param enumration {@link Enumeration} + * @param enumeration {@link Enumeration} * @return ArrayList对象 * @since 3.0.8 */ - public static ArrayList newArrayList(Enumeration enumration) { - return (ArrayList) list(false, enumration); + public static ArrayList newArrayList(Enumeration enumeration) { + return ListUtil.toList(enumeration); } // ----------------------------------------------------------------------new LinkedList @@ -741,7 +742,7 @@ public class CollUtil { */ @SafeVarargs public static LinkedList newLinkedList(T... values) { - return (LinkedList) list(true, values); + return ListUtil.toLinkedList(values); } /** @@ -752,7 +753,7 @@ public class CollUtil { * @return {@link CopyOnWriteArrayList} */ public static CopyOnWriteArrayList newCopyOnWriteArrayList(Collection collection) { - return (null == collection) ? (new CopyOnWriteArrayList<>()) : (new CopyOnWriteArrayList<>(collection)); + return ListUtil.toCopyOnWriteArrayList(collection); } /** @@ -862,7 +863,7 @@ public class CollUtil { * @return 截取后的数组,当开始位置超过最大时,返回空的List */ public static List sub(List list, int start, int end) { - return sub(list, start, end, 1); + return ListUtil.sub(list, start, end); } /** @@ -877,45 +878,7 @@ public class CollUtil { * @since 4.0.6 */ public static List sub(List list, int start, int end, int step) { - if (list == null) { - return null; - } - - if (list.isEmpty()) { - return new ArrayList<>(0); - } - - final int size = list.size(); - if (start < 0) { - start += size; - } - if (end < 0) { - end += size; - } - if (start == size) { - return new ArrayList<>(0); - } - if (start > end) { - int tmp = start; - start = end; - end = tmp; - } - if (end > size) { - if (start >= size) { - return new ArrayList<>(0); - } - end = size; - } - - if (step <= 1) { - return list.subList(start, end); - } - - final List result = new ArrayList<>(); - for (int i = start; i < end; i += step) { - result.add(list.get(i)); - } - return result; + return ListUtil.sub(list, start, end, step); } /** @@ -1026,19 +989,7 @@ public class CollUtil { * @since 4.1.8 */ public static List filter(List list, Editor editor) { - if (null == list || null == editor) { - return list; - } - - final List list2 = (list instanceof LinkedList) ? new LinkedList<>() : new ArrayList<>(list.size()); - T modified; - for (T t : list) { - modified = editor.edit(t); - if (null != modified) { - list2.add(modified); - } - } - return list2; + return ListUtil.filter(list, editor); } /** @@ -1091,16 +1042,7 @@ public class CollUtil { * @since 4.1.8 */ public static List filterNew(List list, Filter filter) { - if (null == list || null == filter) { - return list; - } - final List list2 = (list instanceof LinkedList) ? new LinkedList<>() : new ArrayList<>(list.size()); - for (T t : list) { - if (filter.accept(t)) { - list2.add(t); - } - } - return list2; + return ListUtil.filter(list, t -> filter.accept(t) ? t : null); } /** @@ -2121,25 +2063,7 @@ public class CollUtil { * @since 4.1.20 */ public static List page(int pageNo, int pageSize, List list) { - if (isEmpty(list)) { - return new ArrayList<>(0); - } - - int resultSize = list.size(); - // 每页条目数大于总数直接返回所有 - if (resultSize <= pageSize) { - if (pageNo < 1) { - return Collections.unmodifiableList(list); - } else { - // 越界直接返回空 - return new ArrayList<>(0); - } - } - final int[] startEnd = PageUtil.transToStartEnd(pageNo, pageSize); - if (startEnd[1] > resultSize) { - startEnd[1] = resultSize; - } - return list.subList(startEnd[0], startEnd[1]); + return ListUtil.page(pageNo, pageSize, list); } /** @@ -2166,8 +2090,7 @@ public class CollUtil { * @see Collections#sort(List, Comparator) */ public static List sort(List list, Comparator c) { - list.sort(c); - return list; + return ListUtil.sort(list, c); } /** @@ -2193,7 +2116,7 @@ public class CollUtil { * @since 4.0.6 */ public static List sortByProperty(List list, String property) { - return sort(list, new PropertyComparator<>(property)); + return ListUtil.sortByProperty(list, property); } /** @@ -2215,7 +2138,7 @@ public class CollUtil { * @since 4.0.8 */ public static List sortByPinyin(List list) { - return sort(list, new PinyinComparator()); + return ListUtil.sortByPinyin(list); } /** @@ -2342,14 +2265,14 @@ public class CollUtil { } /** - * 分组,按照{@link Hash}接口定义的hash算法,集合中的元素放入hash值对应的子列表中 + * 分组,按照{@link Hash32}接口定义的hash算法,集合中的元素放入hash值对应的子列表中 * * @param 元素类型 * @param collection 被分组的集合 * @param hash Hash值算法,决定元素放在第几个分组的规则 * @return 分组后的集合 */ - public static List> group(Collection collection, Hash hash) { + public static List> group(Collection collection, Hash32 hash) { final List> result = new ArrayList<>(); if (isEmpty(collection)) { return result; @@ -2362,7 +2285,7 @@ public class CollUtil { int index; List subList; for (T t : collection) { - index = hash.hash(t); + index = hash.hash32(t); if (result.size() - 1 < index) { while (result.size() - 1 < index) { result.add(null); @@ -2389,11 +2312,11 @@ public class CollUtil { * @return 分组列表 */ public static List> groupByField(Collection collection, final String fieldName) { - return group(collection, new Hash() { + return group(collection, new Hash32() { private final List fieldNameList = new ArrayList<>(); @Override - public int hash(T t) { + public int hash32(T t) { if (null == t || false == BeanUtil.isBean(t.getClass())) { // 非Bean放在同一子分组中 return 0; @@ -2419,8 +2342,7 @@ public class CollUtil { * @since 4.0.6 */ public static List reverse(List list) { - Collections.reverse(list); - return list; + return ListUtil.reverse(list); } /** @@ -2432,8 +2354,7 @@ public class CollUtil { * @since 4.0.6 */ public static List reverseNew(List list) { - final List list2 = ObjectUtil.clone(list); - return reverse(list2); + return ListUtil.reverseNew(list); } /** @@ -2447,12 +2368,7 @@ public class CollUtil { * @since 4.1.2 */ public static List setOrAppend(List list, int index, T element) { - if (index < list.size()) { - list.set(index, element); - } else { - list.add(element); - } - return list; + return ListUtil.setOrAppend(list, index, element); } /** @@ -2553,22 +2469,5 @@ public class CollUtil { */ void accept(K key, V value, int index); } - - /** - * Hash计算接口 - * - * @param 被计算hash的对象类型 - * @author looly - * @since 3.2.2 - */ - public interface Hash { - /** - * 计算Hash值 - * - * @param t 对象 - * @return hash - */ - int hash(T t); - } // ---------------------------------------------------------------------------------------------- Interface end } diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java b/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java new file mode 100644 index 000000000..66a4659fa --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java @@ -0,0 +1,448 @@ +package cn.hutool.core.collection; + +import cn.hutool.core.comparator.PinyinComparator; +import cn.hutool.core.comparator.PropertyComparator; +import cn.hutool.core.lang.Editor; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.PageUtil; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +public class ListUtil { + /** + * 新建一个空List + * + * @param 集合元素类型 + * @param isLinked 是否新建LinkedList + * @return List对象 + * @since 4.1.2 + */ + public static List list(boolean isLinked) { + return isLinked ? new LinkedList<>() : new ArrayList<>(); + } + + /** + * 新建一个List + * + * @param 集合元素类型 + * @param isLinked 是否新建LinkedList + * @param values 数组 + * @return List对象 + * @since 4.1.2 + */ + @SafeVarargs + public static List list(boolean isLinked, T... values) { + if (ArrayUtil.isEmpty(values)) { + return list(isLinked); + } + final List arrayList = isLinked ? new LinkedList<>() : new ArrayList<>(values.length); + Collections.addAll(arrayList, values); + return arrayList; + } + + /** + * 新建一个List + * + * @param 集合元素类型 + * @param isLinked 是否新建LinkedList + * @param collection 集合 + * @return List对象 + * @since 4.1.2 + */ + public static List list(boolean isLinked, Collection collection) { + if (null == collection) { + return list(isLinked); + } + return isLinked ? new LinkedList<>(collection) : new ArrayList<>(collection); + } + + /** + * 新建一个List
+ * 提供的参数为null时返回空{@link ArrayList} + * + * @param 集合元素类型 + * @param isLinked 是否新建LinkedList + * @param iterable {@link Iterable} + * @return List对象 + * @since 4.1.2 + */ + public static List list(boolean isLinked, Iterable iterable) { + if (null == iterable) { + return list(isLinked); + } + return list(isLinked, iterable.iterator()); + } + + /** + * 新建一个ArrayList
+ * 提供的参数为null时返回空{@link ArrayList} + * + * @param 集合元素类型 + * @param isLinked 是否新建LinkedList + * @param iter {@link Iterator} + * @return ArrayList对象 + * @since 4.1.2 + */ + public static List list(boolean isLinked, Iterator iter) { + final List list = list(isLinked); + if (null != iter) { + while (iter.hasNext()) { + list.add(iter.next()); + } + } + return list; + } + + /** + * 新建一个List
+ * 提供的参数为null时返回空{@link ArrayList} + * + * @param 集合元素类型 + * @param isLinked 是否新建LinkedList + * @param enumration {@link Enumeration} + * @return ArrayList对象 + * @since 3.0.8 + */ + public static List list(boolean isLinked, Enumeration enumration) { + final List list = list(isLinked); + if (null != enumration) { + while (enumration.hasMoreElements()) { + list.add(enumration.nextElement()); + } + } + return list; + } + + /** + * 新建一个ArrayList + * + * @param 集合元素类型 + * @param values 数组 + * @return ArrayList对象 + */ + @SafeVarargs + public static ArrayList toList(T... values) { + return (ArrayList) list(false, values); + } + + /** + * 新建LinkedList + * + * @param values 数组 + * @param 类型 + * @return LinkedList + * @since 4.1.2 + */ + @SafeVarargs + public static LinkedList toLinkedList(T... values) { + return (LinkedList) list(true, values); + } + + /** + * 新建一个CopyOnWriteArrayList + * + * @param 集合元素类型 + * @param collection 集合 + * @return {@link CopyOnWriteArrayList} + */ + public static CopyOnWriteArrayList toCopyOnWriteArrayList(Collection collection) { + return (null == collection) ? (new CopyOnWriteArrayList<>()) : (new CopyOnWriteArrayList<>(collection)); + } + + /** + * 新建一个ArrayList + * + * @param 集合元素类型 + * @param collection 集合 + * @return ArrayList对象 + */ + public static ArrayList toList(Collection collection) { + return (ArrayList) list(false, collection); + } + + /** + * 新建一个ArrayList
+ * 提供的参数为null时返回空{@link ArrayList} + * + * @param 集合元素类型 + * @param iterable {@link Iterable} + * @return ArrayList对象 + * @since 3.1.0 + */ + public static ArrayList toList(Iterable iterable) { + return (ArrayList) list(false, iterable); + } + + /** + * 新建一个ArrayList
+ * 提供的参数为null时返回空{@link ArrayList} + * + * @param 集合元素类型 + * @param iterator {@link Iterator} + * @return ArrayList对象 + * @since 3.0.8 + */ + public static ArrayList toList(Iterator iterator) { + return (ArrayList) list(false, iterator); + } + + /** + * 新建一个ArrayList
+ * 提供的参数为null时返回空{@link ArrayList} + * + * @param 集合元素类型 + * @param enumeration {@link Enumeration} + * @return ArrayList对象 + * @since 3.0.8 + */ + public static ArrayList toList(Enumeration enumeration) { + return (ArrayList) list(false, enumeration); + } + + /** + * 对指定List分页取值 + * + * @param 集合元素类型 + * @param pageNo 页码,从0开始计数,0表示第一页 + * @param pageSize 每页的条目数 + * @param list 列表 + * @return 分页后的段落内容 + * @since 4.1.20 + */ + public static List page(int pageNo, int pageSize, List list) { + if (CollUtil.isEmpty(list)) { + return new ArrayList<>(0); + } + + int resultSize = list.size(); + // 每页条目数大于总数直接返回所有 + if (resultSize <= pageSize) { + if (pageNo < 1) { + return Collections.unmodifiableList(list); + } else { + // 越界直接返回空 + return new ArrayList<>(0); + } + } + final int[] startEnd = PageUtil.transToStartEnd(pageNo, pageSize); + if (startEnd[1] > resultSize) { + startEnd[1] = resultSize; + } + return list.subList(startEnd[0], startEnd[1]); + } + + /** + * 针对List排序,排序会修改原List + * + * @param 元素类型 + * @param list 被排序的List + * @param c {@link Comparator} + * @return 原list + * @see Collections#sort(List, Comparator) + */ + public static List sort(List list, Comparator c) { + list.sort(c); + return list; + } + + /** + * 根据Bean的属性排序 + * + * @param 元素类型 + * @param list List + * @param property 属性名 + * @return 排序后的List + * @since 4.0.6 + */ + public static List sortByProperty(List list, String property) { + return sort(list, new PropertyComparator<>(property)); + } + + /** + * 根据汉字的拼音顺序排序 + * + * @param list List + * @return 排序后的List + * @since 4.0.8 + */ + public static List sortByPinyin(List list) { + return sort(list, new PinyinComparator()); + } + + /** + * 反序给定List,会在原List基础上直接修改 + * + * @param 元素类型 + * @param list 被反转的List + * @return 反转后的List + * @since 4.0.6 + */ + public static List reverse(List list) { + Collections.reverse(list); + return list; + } + + /** + * 反序给定List,会创建一个新的List,原List数据不变 + * + * @param 元素类型 + * @param list 被反转的List + * @return 反转后的List + * @since 4.0.6 + */ + public static List reverseNew(List list) { + final List list2 = ObjectUtil.clone(list); + return reverse(list2); + } + + /** + * 设置或增加元素。当index小于List的长度时,替换指定位置的值,否则在尾部追加 + * + * @param 元素类型 + * @param list List列表 + * @param index 位置 + * @param element 新元素 + * @return 原List + * @since 4.1.2 + */ + public static List setOrAppend(List list, int index, T element) { + if (index < list.size()) { + list.set(index, element); + } else { + list.add(element); + } + return list; + } + + /** + * 截取集合的部分 + * + * @param 集合元素类型 + * @param list 被截取的数组 + * @param start 开始位置(包含) + * @param end 结束位置(不包含) + * @return 截取后的数组,当开始位置超过最大时,返回空的List + */ + public static List sub(List list, int start, int end) { + return sub(list, start, end, 1); + } + + /** + * 截取集合的部分 + * + * @param 集合元素类型 + * @param list 被截取的数组 + * @param start 开始位置(包含) + * @param end 结束位置(不包含) + * @param step 步进 + * @return 截取后的数组,当开始位置超过最大时,返回空的List + * @since 4.0.6 + */ + public static List sub(List list, int start, int end, int step) { + if (list == null) { + return null; + } + + if (list.isEmpty()) { + return new ArrayList<>(0); + } + + final int size = list.size(); + if (start < 0) { + start += size; + } + if (end < 0) { + end += size; + } + if (start == size) { + return new ArrayList<>(0); + } + if (start > end) { + int tmp = start; + start = end; + end = tmp; + } + if (end > size) { + if (start >= size) { + return new ArrayList<>(0); + } + end = size; + } + + if (step <= 1) { + return list.subList(start, end); + } + + final List result = new ArrayList<>(); + for (int i = start; i < end; i += step) { + result.add(list.get(i)); + } + return result; + } + + /** + * 编辑列表,此方法会修改原列表的内容
+ * 编辑过程通过传入的Editor实现编辑列表中元素内容,这个Editor实现可以实现以下功能: + * + *
+	 *  1、修改元素对象,返回集合中为修改后的对象
+	 * 
+ * + * @param 集合元素类型 + * @param list 集合 + * @param editor 编辑器接口 + * @return 编辑后的数组 + * @since 4.1.8 + */ + public static List edit(List list, Editor editor) { + if (null == list || null == editor) { + return list; + } + + for (T t : list) { + editor.edit(t); + } + + return list; + } + + /** + * 过滤
+ * 过滤过程通过传入的Editor实现来返回需要的元素内容,这个Editor实现可以实现以下功能: + * + *
+	 * 1、过滤出需要的对象,如果返回null表示这个元素对象抛弃
+	 * 2、修改元素对象,返回集合中为修改后的对象
+	 * 
+ * + * @param 集合元素类型 + * @param list 集合 + * @param editor 编辑器接口 + * @return 过滤后的数组 + * @since 4.1.8 + */ + public static List filter(List list, Editor editor) { + if (null == list || null == editor) { + return list; + } + + final List list2 = (list instanceof LinkedList) ? new LinkedList<>() : new ArrayList<>(list.size()); + T modified; + for (T t : list) { + modified = editor.edit(t); + if (null != modified) { + list2.add(modified); + } + } + return list2; + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/ConsistentHash.java b/hutool-core/src/main/java/cn/hutool/core/lang/ConsistentHash.java index 637af8b01..84be21410 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/ConsistentHash.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/ConsistentHash.java @@ -1,5 +1,6 @@ package cn.hutool.core.lang; +import cn.hutool.core.lang.hash.Hash32; import cn.hutool.core.util.HashUtil; import java.io.Serializable; @@ -19,7 +20,7 @@ public class ConsistentHash implements Serializable{ private static final long serialVersionUID = 1L; /** Hash计算对象,用于自定义hash算法 */ - HashFunc hashFunc; + Hash32 hashFunc; /** 复制的节点个数 */ private final int numberOfReplicas; /** 一致性Hash环 */ @@ -48,7 +49,7 @@ public class ConsistentHash implements Serializable{ * @param numberOfReplicas 复制的节点个数,增加每个节点的复制节点有利于负载均衡 * @param nodes 节点对象 */ - public ConsistentHash(HashFunc hashFunc, int numberOfReplicas, Collection nodes) { + public ConsistentHash(Hash32 hashFunc, int numberOfReplicas, Collection nodes) { this.numberOfReplicas = numberOfReplicas; this.hashFunc = hashFunc; //初始化节点 @@ -66,7 +67,7 @@ public class ConsistentHash implements Serializable{ */ public void add(T node) { for (int i = 0; i < numberOfReplicas; i++) { - circle.put(hashFunc.hash(node.toString() + i), node); + circle.put(hashFunc.hash32(node.toString() + i), node); } } @@ -76,7 +77,7 @@ public class ConsistentHash implements Serializable{ */ public void remove(T node) { for (int i = 0; i < numberOfReplicas; i++) { - circle.remove(hashFunc.hash(node.toString() + i)); + circle.remove(hashFunc.hash32(node.toString() + i)); } } @@ -89,21 +90,12 @@ public class ConsistentHash implements Serializable{ if (circle.isEmpty()) { return null; } - int hash = hashFunc.hash(key); - if (!circle.containsKey(hash)) { + int hash = hashFunc.hash32(key); + if (false == circle.containsKey(hash)) { SortedMap tailMap = circle.tailMap(hash); //返回此映射的部分视图,其键大于等于 hash hash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey(); } //正好命中 return circle.get(hash); } - - /** - * Hash算法对象,用于自定义hash算法 - * @author xiaoleilu - * - */ - public interface HashFunc { - Integer hash(Object key); - } } \ No newline at end of file diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/hash/Hash128.java b/hutool-core/src/main/java/cn/hutool/core/lang/hash/Hash128.java new file mode 100644 index 000000000..768eaff78 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/lang/hash/Hash128.java @@ -0,0 +1,19 @@ +package cn.hutool.core.lang.hash; + +/** + * Hash计算接口 + * + * @param 被计算hash的对象类型 + * @author looly + * @since 5.2.5 + */ +@FunctionalInterface +public interface Hash128 { + /** + * 计算Hash值 + * + * @param t 对象 + * @return hash + */ + Number128 hash128(T t); +} \ No newline at end of file diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/hash/Hash32.java b/hutool-core/src/main/java/cn/hutool/core/lang/hash/Hash32.java new file mode 100644 index 000000000..113d91c9b --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/lang/hash/Hash32.java @@ -0,0 +1,19 @@ +package cn.hutool.core.lang.hash; + +/** + * Hash计算接口 + * + * @param 被计算hash的对象类型 + * @author looly + * @since 5.2.5 + */ +@FunctionalInterface +public interface Hash32 { + /** + * 计算Hash值 + * + * @param t 对象 + * @return hash + */ + int hash32(T t); +} \ No newline at end of file diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/hash/Hash64.java b/hutool-core/src/main/java/cn/hutool/core/lang/hash/Hash64.java new file mode 100644 index 000000000..332986d82 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/lang/hash/Hash64.java @@ -0,0 +1,19 @@ +package cn.hutool.core.lang.hash; + +/** + * Hash计算接口 + * + * @param 被计算hash的对象类型 + * @author looly + * @since 5.2.5 + */ +@FunctionalInterface +public interface Hash64 { + /** + * 计算Hash值 + * + * @param t 对象 + * @return hash + */ + long hash64(T t); +} \ No newline at end of file diff --git a/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java index ef14dc3a9..d473f2f58 100644 --- a/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java @@ -121,6 +121,15 @@ public class CollUtilTest { Assert.assertTrue(disjunction2.contains("c")); } + @Test + public void subtractTest(){ + List list1 = CollUtil.newArrayList("a", "b", "b", "c", "d", "x"); + List list2 = CollUtil.newArrayList("a", "b", "b", "b", "c", "d", "x2"); + final Collection subtract = CollUtil.subtract(list1, list2); + Assert.assertEquals(1, subtract.size()); + Assert.assertEquals("x", subtract.iterator().next()); + } + @Test public void toMapListAndToListMapTest() { HashMap map1 = new HashMap<>(); @@ -346,8 +355,7 @@ public class CollUtilTest { @Test public void getTest() { - @SuppressWarnings("RedundantArrayCreation") - HashSet set = CollUtil.newHashSet(true, new String[] { "A", "B", "C", "D" }); + HashSet set = CollUtil.set(true, "A", "B", "C", "D"); String str = CollUtil.get(set, 2); Assert.assertEquals("C", str);