diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/CheckedLinkedBlockingQueue.java b/hutool-core/src/main/java/cn/hutool/core/collection/CheckedLinkedBlockingQueue.java new file mode 100644 index 000000000..5e0161ca5 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/collection/CheckedLinkedBlockingQueue.java @@ -0,0 +1,57 @@ +package cn.hutool.core.collection; + +import java.util.Collection; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; + +/** + * 自定义加入前检查的{@link LinkedBlockingQueue},给定一个检查函数,在加入元素前检查此函数
+ * 原理是通过Runtime#freeMemory()获取剩余内存,当剩余内存低于指定的阈值时,不再加入。 + * + * @author looly + * @since 6.0.0 + */ +public class CheckedLinkedBlockingQueue extends LinkedBlockingQueue { + private static final long serialVersionUID = 1L; + + protected final Predicate checker; + + /** + * 构造 + * + * @param checker 检查函数 + */ + public CheckedLinkedBlockingQueue(final Predicate checker) { + super(Integer.MAX_VALUE); + this.checker = checker; + } + + /** + * 构造 + * + * @param c 初始集合 + * @param checker 检查函数 + */ + public CheckedLinkedBlockingQueue(final Collection c, final Predicate checker) { + super(c); + this.checker = checker; + } + + @Override + public void put(final E e) throws InterruptedException { + if (checker.test(e)) { + super.put(e); + } + } + + @Override + public boolean offer(final E e, final long timeout, final TimeUnit unit) throws InterruptedException { + return checker.test(e) && super.offer(e, timeout, unit); + } + + @Override + public boolean offer(final E e) { + return checker.test(e) && super.offer(e); + } +} 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 988103e50..ee785fa96 100755 --- a/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java @@ -11,16 +11,14 @@ import cn.hutool.core.comparator.PropertyComparator; import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.ConverterRegistry; import cn.hutool.core.exceptions.UtilException; -import cn.hutool.core.lang.func.Editor; -import cn.hutool.core.lang.func.Filter; import cn.hutool.core.lang.func.Func1; -import cn.hutool.core.lang.func.Matcher; import cn.hutool.core.lang.hash.Hash32; import cn.hutool.core.map.MapUtil; import cn.hutool.core.reflect.ClassUtil; import cn.hutool.core.reflect.ConstructorUtil; import cn.hutool.core.reflect.FieldUtil; import cn.hutool.core.reflect.TypeUtil; +import cn.hutool.core.stream.StreamUtil; import cn.hutool.core.text.StrUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.CharUtil; @@ -60,6 +58,8 @@ import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; +import java.util.function.UnaryOperator; +import java.util.stream.Collectors; /** * 集合相关工具类 @@ -74,6 +74,90 @@ import java.util.function.Supplier; */ public class CollUtil { + // ---------------------------------------------------------------------- isEmpty + + /** + * 集合是否为空 + * + * @param collection 集合 + * @return 是否为空 + */ + public static boolean isEmpty(final Collection collection) { + return collection == null || collection.isEmpty(); + } + + /** + * Iterable是否为空 + * + * @param iterable Iterable对象 + * @return 是否为空 + * @see IterUtil#isEmpty(Iterable) + */ + public static boolean isEmpty(final Iterable iterable) { + return IterUtil.isEmpty(iterable); + } + + /** + * Iterator是否为空 + * + * @param Iterator Iterator对象 + * @return 是否为空 + * @see IterUtil#isEmpty(Iterator) + */ + public static boolean isEmpty(final Iterator Iterator) { + return IterUtil.isEmpty(Iterator); + } + + /** + * Enumeration是否为空 + * + * @param enumeration {@link Enumeration} + * @return 是否为空 + */ + public static boolean isEmpty(final Enumeration enumeration) { + return null == enumeration || false == enumeration.hasMoreElements(); + } + + /** + * Map是否为空 + * + * @param map 集合 + * @return 是否为空 + * @see MapUtil#isEmpty(Map) + * @since 5.7.4 + */ + public static boolean isEmpty(final Map map) { + return MapUtil.isEmpty(map); + } + + /** + * 如果给定集合为空,返回默认集合 + * + * @param 集合类型 + * @param 集合元素类型 + * @param collection 集合 + * @param defaultCollection 默认数组 + * @return 非空(empty)的原集合或默认集合 + * @since 4.6.9 + */ + public static , E> T defaultIfEmpty(final T collection, final T defaultCollection) { + return isEmpty(collection) ? defaultCollection : collection; + } + + /** + * 如果给定集合为空,返回默认集合 + * + * @param 集合类型 + * @param 集合元素类型 + * @param collection 集合 + * @param supplier 默认值懒加载函数 + * @return 非空(empty)的原集合或默认集合 + * @since 5.7.15 + */ + public static , E> T defaultIfEmpty(final T collection, final Supplier supplier) { + return isEmpty(collection) ? supplier.get() : collection; + } + /** * 如果提供的集合为{@code null},返回一个不可变的默认空集合,否则返回原集合
* 空集合使用{@link Collections#emptySet()} @@ -84,7 +168,7 @@ public class CollUtil { * @since 4.6.3 */ public static Set emptyIfNull(final Set set) { - return (null == set) ? Collections.emptySet() : set; + return ObjUtil.defaultIfNull(set, Collections.emptySet()); } /** @@ -97,7 +181,118 @@ public class CollUtil { * @since 4.6.3 */ public static List emptyIfNull(final List list) { - return (null == list) ? Collections.emptyList() : list; + return ObjUtil.defaultIfNull(list, Collections.emptyList()); + } + + // ---------------------------------------------------------------------- isNotEmpty + + /** + * 集合是否为非空 + * + * @param collection 集合 + * @return 是否为非空 + */ + public static boolean isNotEmpty(final Collection collection) { + return false == isEmpty(collection); + } + + /** + * Iterable是否为空 + * + * @param iterable Iterable对象 + * @return 是否为空 + * @see IterUtil#isNotEmpty(Iterable) + */ + public static boolean isNotEmpty(final Iterable iterable) { + return IterUtil.isNotEmpty(iterable); + } + + /** + * Iterator是否为空 + * + * @param Iterator Iterator对象 + * @return 是否为空 + * @see IterUtil#isNotEmpty(Iterator) + */ + public static boolean isNotEmpty(final Iterator Iterator) { + return IterUtil.isNotEmpty(Iterator); + } + + /** + * Enumeration是否为空 + * + * @param enumeration {@link Enumeration} + * @return 是否为空 + */ + public static boolean isNotEmpty(final Enumeration enumeration) { + return null != enumeration && enumeration.hasMoreElements(); + } + + /** + * 是否包含{@code null}元素 + * + * @param iterable 被检查的Iterable对象,如果为{@code null} 返回true + * @return 是否包含{@code null}元素 + * @see IterUtil#hasNull(Iterable) + * @since 3.0.7 + */ + public static boolean hasNull(final Iterable iterable) { + return IterUtil.hasNull(iterable); + } + + /** + * Map是否为非空 + * + * @param map 集合 + * @return 是否为非空 + * @see MapUtil#isNotEmpty(Map) + * @since 5.7.4 + */ + public static boolean isNotEmpty(final Map map) { + return MapUtil.isNotEmpty(map); + } + + /** + * 去重集合 + * + * @param 集合元素类型 + * @param collection 集合 + * @return {@link ArrayList} + */ + public static ArrayList distinct(final Collection collection) { + if (isEmpty(collection)) { + return new ArrayList<>(); + } else if (collection instanceof Set) { + return new ArrayList<>(collection); + } else { + return new ArrayList<>(new LinkedHashSet<>(collection)); + } + } + + /** + * 根据函数生成的KEY去重集合,如根据Bean的某个或者某些字段完成去重。
+ * 去重可选是保留最先加入的值还是后加入的值 + * + * @param 集合元素类型 + * @param 唯一键类型 + * @param collection 集合 + * @param uniqueGenerator 唯一键生成器 + * @param override 是否覆盖模式,如果为{@code true},加入的新值会覆盖相同key的旧值,否则会忽略新加值 + * @return {@link ArrayList} + * @since 5.8.0 + */ + public static List distinct(final Collection collection, final Function uniqueGenerator, final boolean override) { + if (isEmpty(collection)) { + return new ArrayList<>(); + } + + final UniqueKeySet set = new UniqueKeySet<>(true, uniqueGenerator); + if (override) { + set.addAll(collection); + } else { + set.addAllIfAbsent(collection); + } + return new ArrayList<>(set); } /** @@ -729,49 +924,6 @@ public class CollUtil { return list; } - /** - * 去重集合 - * - * @param 集合元素类型 - * @param collection 集合 - * @return {@link ArrayList} - */ - public static ArrayList distinct(final Collection collection) { - if (isEmpty(collection)) { - return new ArrayList<>(); - } else if (collection instanceof Set) { - return new ArrayList<>(collection); - } else { - return new ArrayList<>(new LinkedHashSet<>(collection)); - } - } - - /** - * 根据函数生成的KEY去重集合,如根据Bean的某个或者某些字段完成去重。
- * 去重可选是保留最先加入的值还是后加入的值 - * - * @param 集合元素类型 - * @param 唯一键类型 - * @param collection 集合 - * @param uniqueGenerator 唯一键生成器 - * @param override 是否覆盖模式,如果为{@code true},加入的新值会覆盖相同key的旧值,否则会忽略新加值 - * @return {@link ArrayList} - * @since 5.8.0 - */ - public static List distinct(final Collection collection, final Function uniqueGenerator, final boolean override) { - if (isEmpty(collection)) { - return new ArrayList<>(); - } - - final UniqueKeySet set = new UniqueKeySet<>(true, uniqueGenerator); - if (override) { - set.addAll(collection); - } else { - set.addAllIfAbsent(collection); - } - return new ArrayList<>(set); - } - /** * 截取列表的部分 * @@ -875,7 +1027,7 @@ public class CollUtil { * @param editor 编辑器接口,{@code null}返回原集合 * @return 过滤后的集合 */ - public static Collection edit(final Collection collection, final Editor editor) { + public static Collection edit(final Collection collection, final UnaryOperator editor) { if (null == collection || null == editor) { return collection; } @@ -887,7 +1039,7 @@ public class CollUtil { T modified; for (final T t : collection) { - modified = editor.edit(t); + modified = editor.apply(t); if (null != modified) { collection2.add(modified); } @@ -897,23 +1049,23 @@ public class CollUtil { /** * 过滤
- * 过滤过程通过传入的Filter实现来过滤返回需要的元素内容,这个Filter实现可以实现以下功能: + * 过滤过程通过传入的{@link Predicate}实现来过滤返回需要的元素内容,可以实现以下功能: * *
-	 * 1、过滤出需要的对象,{@link Filter#accept(Object)}方法返回true的对象将被加入结果集合中
+	 * 1、过滤出需要的对象,{@link Predicate#test(Object)}方法返回true的对象将被加入结果集合中
 	 * 
* * @param 集合元素类型 * @param collection 集合 - * @param filter 过滤器,{@code null}返回原集合 + * @param predicate 过滤器,{@code null}返回原集合 * @return 过滤后的数组 - * @since 3.1.0 + * @since 6.0.0 */ - public static Collection filterNew(final Collection collection, final Filter filter) { - if (null == collection || null == filter) { + public static Collection filter(final Collection collection, final Predicate predicate) { + if (null == collection || null == predicate) { return collection; } - return edit(collection, t -> filter.accept(t) ? t : null); + return edit(collection, t -> predicate.test(t) ? t : null); } /** @@ -942,8 +1094,8 @@ public class CollUtil { * @return 处理后的集合 * @since 4.6.5 */ - public static , E> T filter(final T collection, final Predicate filter) { - return IterUtil.filter(collection, filter); + public static , E> T remove(final T collection, final Predicate filter) { + return IterUtil.remove(collection, filter); } /** @@ -956,7 +1108,7 @@ public class CollUtil { * @since 3.2.2 */ public static , E> T removeNull(final T collection) { - return filter(collection, Objects::nonNull); + return remove(collection, Objects::isNull); } /** @@ -969,7 +1121,7 @@ public class CollUtil { * @since 3.2.2 */ public static , E extends CharSequence> T removeEmpty(final T collection) { - return filter(collection, StrUtil::isNotEmpty); + return remove(collection, StrUtil::isEmpty); } /** @@ -982,7 +1134,7 @@ public class CollUtil { * @since 3.2.2 */ public static , E extends CharSequence> T removeBlank(final T collection) { - return filter(collection, StrUtil::isNotBlank); + return remove(collection, StrUtil::isBlank); } /** @@ -1028,30 +1180,19 @@ public class CollUtil { } /** - * 通过Editor抽取集合元素中的某些值返回为新列表
- * 例如提供的是一个Bean列表,通过Editor接口实现获取某个字段值,返回这个字段值组成的新列表 + * 通过func自定义一个规则,此规则将原集合中的元素转换成新的元素,生成新的列表返回
+ * 例如提供的是一个Bean列表,通过Function接口实现获取某个字段值,返回这个字段值组成的新列表
+ * 默认忽略映射后{@code null}的情况 * + * @param 集合元素类型 + * @param 返回集合元素类型 * @param collection 原集合 - * @param editor 编辑器 + * @param func 编辑函数 * @return 抽取后的新列表 + * @since 5.3.5 */ - public static List extract(final Iterable collection, final Editor editor) { - return extract(collection, editor, false); - } - - /** - * 通过Editor抽取集合元素中的某些值返回为新列表
- * 例如提供的是一个Bean列表,通过Editor接口实现获取某个字段值,返回这个字段值组成的新列表 - * - * @param collection 原集合 - * @param editor 编辑器 - * @param ignoreNull 是否忽略空值 - * @return 抽取后的新列表 - * @see #map(Iterable, Function, boolean) - * @since 4.5.7 - */ - public static List extract(final Iterable collection, final Editor editor, final boolean ignoreNull) { - return map(collection, editor::edit, ignoreNull); + public static List map(final Iterable collection, final Function func) { + return map(collection, func, true); } /** @@ -1061,29 +1202,20 @@ public class CollUtil { * @param 集合元素类型 * @param 返回集合元素类型 * @param collection 原集合 - * @param func 编辑函数 + * @param mapper 编辑函数 * @param ignoreNull 是否忽略空值,这里的空值包括函数处理前和处理后的null值 * @return 抽取后的新列表 + * @see java.util.stream.Stream#map(Function) * @since 5.3.5 */ - public static List map(final Iterable collection, final Function func, final boolean ignoreNull) { - final List fieldValueList = new ArrayList<>(); - if (null == collection) { - return fieldValueList; - } - - R value; - for (final T t : collection) { - if (null == t && ignoreNull) { - continue; - } - value = func.apply(t); - if (null == value && ignoreNull) { - continue; - } - fieldValueList.add(value); - } - return fieldValueList; + public static List map(final Iterable collection, final Function mapper, final boolean ignoreNull) { + return StreamUtil.of(collection) + // 检查映射前的结果 + .filter((e) -> (false == ignoreNull) || null != e) + .map(mapper) + // 检查映射后的结果 + .filter((e) -> (false == ignoreNull) || null != e) + .collect(Collectors.toList()); } /** @@ -1095,7 +1227,7 @@ public class CollUtil { * @return 字段值列表 * @since 3.1.0 */ - public static List getFieldValues(final Iterable collection, final String fieldName) { + public static Collection getFieldValues(final Iterable collection, final String fieldName) { return getFieldValues(collection, fieldName, false); } @@ -1131,7 +1263,7 @@ public class CollUtil { * @since 4.5.6 */ public static List getFieldValues(final Iterable collection, final String fieldName, final Class elementType) { - final List fieldValues = getFieldValues(collection, fieldName); + final Collection fieldValues = getFieldValues(collection, fieldName); return Convert.toList(elementType, fieldValues); } @@ -1170,14 +1302,14 @@ public class CollUtil { * * @param 集合元素类型 * @param collection 集合 - * @param filter 过滤器,满足过滤条件的第一个元素将被返回 + * @param predicate 过滤器,满足过滤条件的第一个元素将被返回 * @return 满足过滤条件的第一个元素 * @since 3.1.0 */ - public static T findOne(final Iterable collection, final Filter filter) { + public static T findOne(final Iterable collection, final Predicate predicate) { if (null != collection) { for (final T t : collection) { - if (filter.accept(t)) { + if (predicate.test(t)) { return t; } } @@ -1215,16 +1347,16 @@ public class CollUtil { /** * 集合中匹配规则的数量 * - * @param 集合元素类型 - * @param iterable {@link Iterable} - * @param matcher 匹配器,为空则全部匹配 + * @param 集合元素类型 + * @param iterable {@link Iterable} + * @param predicate 匹配器,为空则全部匹配 * @return 匹配数量 */ - public static int count(final Iterable iterable, final Matcher matcher) { + public static int count(final Iterable iterable, final Predicate predicate) { int count = 0; if (null != iterable) { for (final T t : iterable) { - if (null == matcher || matcher.match(t)) { + if (null == predicate || predicate.test(t)) { count++; } } @@ -1238,15 +1370,15 @@ public class CollUtil { * * @param 元素类型 * @param collection 集合 - * @param matcher 匹配器,为空则全部匹配 + * @param predicate 匹配器,为空则全部匹配 * @return 第一个位置 * @since 5.6.6 */ - public static int indexOf(final Collection collection, final Matcher matcher) { + public static int indexOf(final Collection collection, final Predicate predicate) { if (isNotEmpty(collection)) { int index = 0; for (final T t : collection) { - if (null == matcher || matcher.match(t)) { + if (null == predicate || predicate.test(t)) { return index; } index++; @@ -1261,20 +1393,20 @@ public class CollUtil { * * @param 元素类型 * @param collection 集合 - * @param matcher 匹配器,为空则全部匹配 + * @param predicate 匹配器,为空则全部匹配 * @return 最后一个位置 * @since 5.6.6 */ - public static int lastIndexOf(final Collection collection, final Matcher matcher) { + public static int lastIndexOf(final Collection collection, final Predicate predicate) { if (collection instanceof List) { // List的查找最后一个有优化算法 - return ListUtil.lastIndexOf((List) collection, matcher); + return ListUtil.lastIndexOf((List) collection, predicate); } int matchIndex = -1; if (isNotEmpty(collection)) { int index = collection.size(); for (final T t : collection) { - if (null == matcher || matcher.match(t)) { + if (null == predicate || predicate.test(t)) { matchIndex = index; } index--; @@ -1289,16 +1421,16 @@ public class CollUtil { * * @param 元素类型 * @param collection 集合 - * @param matcher 匹配器,为空则全部匹配 + * @param predicate 匹配器,为空则全部匹配 * @return 位置数组 * @since 5.2.5 */ - public static int[] indexOfAll(final Collection collection, final Matcher matcher) { + public static int[] indexOfAll(final Collection collection, final Predicate predicate) { final List indexList = new ArrayList<>(); if (null != collection) { int index = 0; for (final T t : collection) { - if (null == matcher || matcher.match(t)) { + if (null == predicate || predicate.test(t)) { indexList.add(index); } index++; @@ -1307,158 +1439,6 @@ public class CollUtil { return Convert.convert(int[].class, indexList); } - // ---------------------------------------------------------------------- isEmpty - - /** - * 集合是否为空 - * - * @param collection 集合 - * @return 是否为空 - */ - public static boolean isEmpty(final Collection collection) { - return collection == null || collection.isEmpty(); - } - - /** - * 如果给定集合为空,返回默认集合 - * - * @param 集合类型 - * @param 集合元素类型 - * @param collection 集合 - * @param defaultCollection 默认数组 - * @return 非空(empty)的原集合或默认集合 - * @since 4.6.9 - */ - public static , E> T defaultIfEmpty(final T collection, final T defaultCollection) { - return isEmpty(collection) ? defaultCollection : collection; - } - - /** - * 如果给定集合为空,返回默认集合 - * - * @param 集合类型 - * @param 集合元素类型 - * @param collection 集合 - * @param supplier 默认值懒加载函数 - * @return 非空(empty)的原集合或默认集合 - * @since 5.7.15 - */ - public static , E> T defaultIfEmpty(final T collection, final Supplier supplier) { - return isEmpty(collection) ? supplier.get() : collection; - } - - /** - * Iterable是否为空 - * - * @param iterable Iterable对象 - * @return 是否为空 - * @see IterUtil#isEmpty(Iterable) - */ - public static boolean isEmpty(final Iterable iterable) { - return IterUtil.isEmpty(iterable); - } - - /** - * Iterator是否为空 - * - * @param Iterator Iterator对象 - * @return 是否为空 - * @see IterUtil#isEmpty(Iterator) - */ - public static boolean isEmpty(final Iterator Iterator) { - return IterUtil.isEmpty(Iterator); - } - - /** - * Enumeration是否为空 - * - * @param enumeration {@link Enumeration} - * @return 是否为空 - */ - public static boolean isEmpty(final Enumeration enumeration) { - return null == enumeration || false == enumeration.hasMoreElements(); - } - - /** - * Map是否为空 - * - * @param map 集合 - * @return 是否为空 - * @see MapUtil#isEmpty(Map) - * @since 5.7.4 - */ - public static boolean isEmpty(final Map map) { - return MapUtil.isEmpty(map); - } - - // ---------------------------------------------------------------------- isNotEmpty - - /** - * 集合是否为非空 - * - * @param collection 集合 - * @return 是否为非空 - */ - public static boolean isNotEmpty(final Collection collection) { - return false == isEmpty(collection); - } - - /** - * Iterable是否为空 - * - * @param iterable Iterable对象 - * @return 是否为空 - * @see IterUtil#isNotEmpty(Iterable) - */ - public static boolean isNotEmpty(final Iterable iterable) { - return IterUtil.isNotEmpty(iterable); - } - - /** - * Iterator是否为空 - * - * @param Iterator Iterator对象 - * @return 是否为空 - * @see IterUtil#isNotEmpty(Iterator) - */ - public static boolean isNotEmpty(final Iterator Iterator) { - return IterUtil.isNotEmpty(Iterator); - } - - /** - * Enumeration是否为空 - * - * @param enumeration {@link Enumeration} - * @return 是否为空 - */ - public static boolean isNotEmpty(final Enumeration enumeration) { - return null != enumeration && enumeration.hasMoreElements(); - } - - /** - * 是否包含{@code null}元素 - * - * @param iterable 被检查的Iterable对象,如果为{@code null} 返回true - * @return 是否包含{@code null}元素 - * @see IterUtil#hasNull(Iterable) - * @since 3.0.7 - */ - public static boolean hasNull(final Iterable iterable) { - return IterUtil.hasNull(iterable); - } - - /** - * Map是否为非空 - * - * @param map 集合 - * @return 是否为非空 - * @see MapUtil#isNotEmpty(Map) - * @since 5.7.4 - */ - public static boolean isNotEmpty(final Map map) { - return MapUtil.isNotEmpty(map); - } - // ---------------------------------------------------------------------- zip /** @@ -1864,23 +1844,6 @@ public class CollUtil { return collection; } - /** - * 将另一个列表中的元素加入到列表中,如果列表中已经存在此元素则忽略之 - * - * @param 集合元素类型 - * @param list 列表 - * @param otherList 其它列表 - * @return 此列表 - */ - public static List addAllIfNotContains(final List list, final List otherList) { - for (final T t : otherList) { - if (false == list.contains(t)) { - list.add(t); - } - } - return list; - } - /** * 获取集合中指定下标的元素值,下标可以为负数,例如-1表示最后一个元素
* 如果元素越界,返回null @@ -2440,7 +2403,7 @@ public class CollUtil { * @since 5.2.6 */ public static Collection unmodifiable(final Collection c) { - if(null == c){ + if (null == c) { return null; } return Collections.unmodifiableCollection(c); 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 index 212150da8..6402dc06e 100755 --- a/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java @@ -7,7 +7,6 @@ import cn.hutool.core.collection.partition.RandomAccessAvgPartition; import cn.hutool.core.collection.partition.RandomAccessPartition; import cn.hutool.core.comparator.PinyinComparator; import cn.hutool.core.comparator.PropertyComparator; -import cn.hutool.core.lang.func.Matcher; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.PageUtil; @@ -23,6 +22,7 @@ import java.util.List; import java.util.RandomAccess; import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.Consumer; +import java.util.function.Predicate; /** * List相关工具类 @@ -473,12 +473,12 @@ public class ListUtil { * @return 最后一个位置 * @since 5.6.6 */ - public static int lastIndexOf(final List list, final Matcher matcher) { + public static int lastIndexOf(final List list, final Predicate matcher) { if (null != list) { final int size = list.size(); if (size > 0) { for (int i = size - 1; i >= 0; i--) { - if (null == matcher || matcher.match(list.get(i))) { + if (null == matcher || matcher.test(list.get(i))) { return i; } } @@ -496,7 +496,7 @@ public class ListUtil { * @return 位置数组 * @since 5.2.5 */ - public static int[] indexOfAll(final List list, final Matcher matcher) { + public static int[] indexOfAll(final List list, final Predicate matcher) { return CollUtil.indexOfAll(list, matcher); } @@ -624,4 +624,21 @@ public class ListUtil { } return Collections.unmodifiableList(c); } + + /** + * 将另一个列表中的元素加入到列表中,如果列表中已经存在此元素则忽略之 + * + * @param 集合元素类型 + * @param list 列表 + * @param otherList 其它列表 + * @return 此列表 + */ + public static List addAllIfNotContains(final List list, final List otherList) { + for (final T t : otherList) { + if (false == list.contains(t)) { + list.add(t); + } + } + return list; + } } diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/MemorySafeLinkedBlockingQueue.java b/hutool-core/src/main/java/cn/hutool/core/collection/MemorySafeLinkedBlockingQueue.java index a22f93097..98146ae89 100644 --- a/hutool-core/src/main/java/cn/hutool/core/collection/MemorySafeLinkedBlockingQueue.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/MemorySafeLinkedBlockingQueue.java @@ -21,7 +21,7 @@ import cn.hutool.core.util.RuntimeUtil; import java.util.Collection; import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; /** * 内存安全的{@link LinkedBlockingQueue},可以解决OOM问题。
@@ -35,10 +35,8 @@ import java.util.concurrent.TimeUnit; * @author incubator-shenyu * @since 6.0.0 */ -public class MemorySafeLinkedBlockingQueue extends LinkedBlockingQueue { - private static final long serialVersionUID = 8032578371749960142L; - - private long maxFreeMemory; +public class MemorySafeLinkedBlockingQueue extends CheckedLinkedBlockingQueue { + private static final long serialVersionUID = 1L; /** * 构造 @@ -46,8 +44,7 @@ public class MemorySafeLinkedBlockingQueue extends LinkedBlockingQueue { * @param maxFreeMemory 最大剩余内存大小,当实际内存小于这个值时,不再加入元素 */ public MemorySafeLinkedBlockingQueue(final long maxFreeMemory) { - super(Integer.MAX_VALUE); - this.maxFreeMemory = maxFreeMemory; + super(new MemoryChecker<>(maxFreeMemory)); } /** @@ -58,8 +55,7 @@ public class MemorySafeLinkedBlockingQueue extends LinkedBlockingQueue { */ public MemorySafeLinkedBlockingQueue(final Collection c, final long maxFreeMemory) { - super(c); - this.maxFreeMemory = maxFreeMemory; + super(c, new MemoryChecker<>(maxFreeMemory)); } /** @@ -68,7 +64,7 @@ public class MemorySafeLinkedBlockingQueue extends LinkedBlockingQueue { * @param maxFreeMemory the max free memory */ public void setMaxFreeMemory(final int maxFreeMemory) { - this.maxFreeMemory = maxFreeMemory; + ((MemoryChecker) this.checker).maxFreeMemory = maxFreeMemory; } /** @@ -77,34 +73,26 @@ public class MemorySafeLinkedBlockingQueue extends LinkedBlockingQueue { * @return the max free memory limit */ public long getMaxFreeMemory() { - return maxFreeMemory; + return ((MemoryChecker) this.checker).maxFreeMemory; } /** - * determine if there is any remaining free memory.
- * 剩余内存是否大于给定阈值 + * 根据剩余内存判定的检查器 * - * @return {@code true}则表示大于阈值,可以加入元素,否则无法加入 + * @param 元素类型 */ - public boolean hasRemainedMemory() { - return FreeMemoryCalculator.INSTANCE.getResult() > maxFreeMemory; - } + private static class MemoryChecker implements Predicate { - @Override - public void put(final E e) throws InterruptedException { - if (hasRemainedMemory()) { - super.put(e); + private long maxFreeMemory; + + private MemoryChecker(final long maxFreeMemory) { + this.maxFreeMemory = maxFreeMemory; } - } - @Override - public boolean offer(final E e, final long timeout, final TimeUnit unit) throws InterruptedException { - return hasRemainedMemory() && super.offer(e, timeout, unit); - } - - @Override - public boolean offer(final E e) { - return hasRemainedMemory() && super.offer(e); + @Override + public boolean test(final E e) { + return FreeMemoryCalculator.INSTANCE.getResult() > maxFreeMemory; + } } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/iter/IterUtil.java b/hutool-core/src/main/java/cn/hutool/core/collection/iter/IterUtil.java index e4dec822d..bbfebb164 100644 --- a/hutool-core/src/main/java/cn/hutool/core/collection/iter/IterUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/iter/IterUtil.java @@ -3,7 +3,6 @@ package cn.hutool.core.collection.iter; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.exceptions.UtilException; import cn.hutool.core.lang.Assert; -import cn.hutool.core.lang.func.Editor; import cn.hutool.core.lang.func.Filter; import cn.hutool.core.lang.func.Func1; import cn.hutool.core.lang.func.Matcher; @@ -30,6 +29,7 @@ import java.util.Objects; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; +import java.util.function.UnaryOperator; /** * {@link Iterable} 和 {@link Iterator} 相关工具类 @@ -682,68 +682,68 @@ public class IterUtil { * @return 过滤后的集合 * @since 5.7.1 */ - public static List edit(final Iterable iter, final Editor editor) { + public static List edit(final Iterator iter, final UnaryOperator editor) { final List result = new ArrayList<>(); if (null == iter) { return result; } T modified; - for (final T t : iter) { - modified = (null == editor) ? t : editor.edit(t); + while(iter.hasNext()){ + modified = (null == editor) ? iter.next() : editor.apply(iter.next()); if (null != modified) { - result.add(t); + result.add(modified); } } return result; } /** - * 过滤集合,此方法在原集合上直接修改
- * 通过实现Filter接口,完成元素的过滤,这个Filter实现可以实现以下功能: + * 移除集合中满足条件的所有元素,此方法在原集合上直接修改
+ * 通过实现{@link Predicate}接口,完成元素的移除,可以实现以下功能: * *
-	 * 1、过滤出需要的对象,{@link Filter#accept(Object)}方法返回false的对象将被使用{@link Iterator#remove()}方法移除
+	 * 1、移除指定对象,{@link Predicate#test(Object)}方法返回{@code true}的对象将被使用{@link Iterator#remove()}方法移除。
 	 * 
* * @param 集合类型 * @param 集合元素类型 * @param iter 集合 - * @param filter 过滤器接口 + * @param predicate 过滤器接口 * @return 编辑后的集合 * @since 4.6.5 */ - public static , E> T filter(final T iter, final Predicate filter) { + public static , E> T remove(final T iter, final Predicate predicate) { if (null == iter) { return null; } - filter(iter.iterator(), filter); + remove(iter.iterator(), predicate); return iter; } /** - * 过滤集合,此方法在原集合上直接修改
- * 通过实现Filter接口,完成元素的过滤,这个Filter实现可以实现以下功能: + * 移除集合中满足条件的所有元素,此方法在原集合上直接修改
+ * 通过实现{@link Predicate}接口,完成元素的移除,可以实现以下功能: * *
-	 * 1、过滤出需要的对象,{@link Filter#accept(Object)}方法返回false的对象将被使用{@link Iterator#remove()}方法移除
+	 * 1、移除指定对象,{@link Predicate#test(Object)}方法返回{@code true}的对象将被使用{@link Iterator#remove()}方法移除。
 	 * 
* * @param 集合元素类型 * @param iter 集合 - * @param filter 过滤器接口,删除{@link Filter#accept(Object)}为{@code false}的元素 + * @param predicate 过滤器接口,删除{@link Predicate#test(Object)}为{@code true}的元素 * @return 编辑后的集合 - * @since 4.6.5 + * @since 6.0.0 */ - public static Iterator filter(final Iterator iter, final Predicate filter) { - if (null == iter || null == filter) { + public static Iterator remove(final Iterator iter, final Predicate predicate) { + if (null == iter || null == predicate) { return iter; } while (iter.hasNext()) { - if (false == filter.test(iter.next())) { + if (predicate.test(iter.next())) { iter.remove(); } } diff --git a/hutool-core/src/main/java/cn/hutool/core/text/dfa/WordTree.java b/hutool-core/src/main/java/cn/hutool/core/text/dfa/WordTree.java index 157c26e44..5c435c138 100755 --- a/hutool-core/src/main/java/cn/hutool/core/text/dfa/WordTree.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/dfa/WordTree.java @@ -223,7 +223,7 @@ public class WordTree extends HashMap { */ public List matchAll(final String text, final int limit, final boolean isDensityMatch, final boolean isGreedMatch) { final List matchAllWords = matchAllWords(text, limit, isDensityMatch, isGreedMatch); - return CollUtil.map(matchAllWords, FoundWord::toString, true); + return CollUtil.map(matchAllWords, FoundWord::toString); } /** 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 5c1eed21e..1d831cab4 100755 --- a/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java @@ -2,6 +2,7 @@ package cn.hutool.core.collection; import cn.hutool.core.comparator.ComparableComparator; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.lang.Console; import cn.hutool.core.map.Dict; import cn.hutool.core.map.MapUtil; import cn.hutool.core.text.StrUtil; @@ -253,7 +254,8 @@ public class CollUtilTest { final Dict v2 = Dict.create().set("age", 13).set("id", 15).set("name", "李四"); final ArrayList list = ListUtil.of(v1, v2); - final List fieldValues = CollUtil.getFieldValues(list, "name"); + final List fieldValues = (List) CollUtil.getFieldValues(list, "name"); + Assert.assertEquals("张三", fieldValues.get(0)); Assert.assertEquals("李四", fieldValues.get(1)); } @@ -284,7 +286,7 @@ public class CollUtilTest { } @Test - public void filterTest() { + public void editTest() { final ArrayList list = ListUtil.of("a", "b", "c"); final Collection filtered = CollUtil.edit(list, t -> t + 1); @@ -293,10 +295,10 @@ public class CollUtilTest { } @Test - public void filterTest2() { + public void removeTest() { final ArrayList list = ListUtil.of("a", "b", "c"); - final ArrayList filtered = CollUtil.filter(list, t -> false == "a".equals(t)); + final ArrayList filtered = CollUtil.remove(list, "a"::equals); // 原地过滤 Assert.assertSame(list, filtered); @@ -304,9 +306,9 @@ public class CollUtilTest { } @Test - public void filterSetTest() { + public void removeForSetTest() { final Set set = SetUtil.ofLinked("a", "b", "", " ", "c"); - final Set filtered = CollUtil.filter(set, StrUtil::isNotBlank); + final Set filtered = CollUtil.remove(set, StrUtil::isBlank); Assert.assertEquals(SetUtil.ofLinked("a", "b", "c"), filtered); } @@ -316,12 +318,12 @@ public class CollUtilTest { final ArrayList list = ListUtil.of("a", "b", "c"); final List removed = new ArrayList<>(); - final ArrayList filtered = CollUtil.filter(list, t -> { + final ArrayList filtered = CollUtil.remove(list, t -> { if("a".equals(t)){ removed.add(t); - return false; + return true; } - return true; + return false; }); Assert.assertEquals(1, removed.size()); @@ -508,22 +510,6 @@ public class CollUtilTest { Assert.assertEquals("D", str); } - @Test - public void addAllIfNotContainsTest() { - final ArrayList list1 = new ArrayList<>(); - list1.add("1"); - list1.add("2"); - final ArrayList list2 = new ArrayList<>(); - list2.add("2"); - list2.add("3"); - CollUtil.addAllIfNotContains(list1, list2); - - Assert.assertEquals(3, list1.size()); - Assert.assertEquals("1", list1.get(0)); - Assert.assertEquals("2", list1.get(1)); - Assert.assertEquals("3", list1.get(2)); - } - @Test public void subInput1PositiveNegativePositiveOutput1() { // Arrange @@ -916,4 +902,31 @@ public class CollUtilTest { private String gender; private Integer id; } + + @Test + public void mapTest(){ + final ArrayList list = ListUtil.of("a", "b", "c"); + final List extract = CollUtil.map(list, (e) -> e + "_1"); + Assert.assertEquals(ListUtil.of("a_1", "b_1", "c_1"), extract); + } + + @Test + public void mapBeanTest(){ + final List people = Arrays.asList( + new Person("aa", 12, "man", 1), + new Person("bb", 13, "woman", 2), + new Person("cc", 14, "man", 3), + new Person("dd", 15, "woman", 4) + ); + + final List extract = CollUtil.map(people, Person::getName); + Assert.assertEquals(ListUtil.of("aa", "bb", "cc", "dd"), extract); + } + + @Test + public void createTest(){ + final Collection collection = CollUtil.create(Collections.emptyList().getClass()); + Console.log(collection.getClass()); + Assert.assertNotNull(collection); + } } diff --git a/hutool-core/src/test/java/cn/hutool/core/collection/IterUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/collection/IterUtilTest.java index da5c3da35..501d1b705 100644 --- a/hutool-core/src/test/java/cn/hutool/core/collection/IterUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/collection/IterUtilTest.java @@ -108,11 +108,11 @@ public class IterUtilTest { } @Test - public void filterTest() { + public void removeTest() { final List obj2 = ListUtil.of("3"); final List obj = ListUtil.of("1", "3"); - IterUtil.filter(obj.iterator(), obj2::contains); + IterUtil.remove(obj.iterator(), (e)-> false == obj2.contains(e)); Assert.assertEquals(1, obj.size()); Assert.assertEquals("3", obj.get(0)); diff --git a/hutool-core/src/test/java/cn/hutool/core/collection/ListUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/collection/ListUtilTest.java index 497b66b34..ac1c2b1fd 100644 --- a/hutool-core/src/test/java/cn/hutool/core/collection/ListUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/collection/ListUtilTest.java @@ -232,4 +232,20 @@ public class ListUtilTest { map = list.get(0); Assert.assertEquals("李四", map.get("2")); } + + @Test + public void addAllIfNotContainsTest() { + final ArrayList list1 = new ArrayList<>(); + list1.add("1"); + list1.add("2"); + final ArrayList list2 = new ArrayList<>(); + list2.add("2"); + list2.add("3"); + ListUtil.addAllIfNotContains(list1, list2); + + Assert.assertEquals(3, list1.size()); + Assert.assertEquals("1", list1.get(0)); + Assert.assertEquals("2", list1.get(1)); + Assert.assertEquals("3", list1.get(2)); + } } diff --git a/hutool-core/src/test/java/cn/hutool/core/collection/MemorySafeLinkedBlockingQueueTest.java b/hutool-core/src/test/java/cn/hutool/core/collection/MemorySafeLinkedBlockingQueueTest.java index 8b1cbd148..fc9ff9533 100644 --- a/hutool-core/src/test/java/cn/hutool/core/collection/MemorySafeLinkedBlockingQueueTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/collection/MemorySafeLinkedBlockingQueueTest.java @@ -1,5 +1,6 @@ package cn.hutool.core.collection; +import cn.hutool.core.util.RandomUtil; import org.junit.Assert; import org.junit.Test; @@ -7,7 +8,12 @@ public class MemorySafeLinkedBlockingQueueTest { @Test public void offerTest(){ - final MemorySafeLinkedBlockingQueue queue = new MemorySafeLinkedBlockingQueue<>(Integer.MAX_VALUE); - Assert.assertFalse(queue.offer("123")); + // 设置初始值达到最大,这样任何时候元素都无法加入队列 + final MemorySafeLinkedBlockingQueue queue = new MemorySafeLinkedBlockingQueue<>(Long.MAX_VALUE); + Assert.assertFalse(queue.offer(RandomUtil.randomString(RandomUtil.randomInt(100)))); + + // 设定一个很小的值,可以成功加入 + queue.setMaxFreeMemory(10); + Assert.assertTrue(queue.offer(RandomUtil.randomString(RandomUtil.randomInt(100)))); } } diff --git a/hutool-cron/src/main/java/cn/hutool/cron/pattern/parser/PartParser.java b/hutool-cron/src/main/java/cn/hutool/cron/pattern/parser/PartParser.java index bcd8f8cd4..70cad5597 100644 --- a/hutool-cron/src/main/java/cn/hutool/cron/pattern/parser/PartParser.java +++ b/hutool-cron/src/main/java/cn/hutool/cron/pattern/parser/PartParser.java @@ -1,6 +1,6 @@ package cn.hutool.cron.pattern.parser; -import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; import cn.hutool.core.date.Month; import cn.hutool.core.date.Week; import cn.hutool.core.math.NumberUtil; @@ -104,7 +104,7 @@ public class PartParser { final List parts = StrUtil.split(value, StrUtil.C_COMMA); for (final String part : parts) { - CollUtil.addAllIfNotContains(values, parseStep(part)); + ListUtil.addAllIfNotContains(values, parseStep(part)); } return values; } diff --git a/hutool-extra/src/main/java/cn/hutool/extra/ssh/Sftp.java b/hutool-extra/src/main/java/cn/hutool/extra/ssh/Sftp.java index a510ecf8a..6bdc57f9c 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/ssh/Sftp.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/ssh/Sftp.java @@ -312,7 +312,7 @@ public class Sftp extends AbstractFtp { if (CollUtil.isEmpty(entries)) { return ListUtil.empty(); } - return CollUtil.map(entries, LsEntry::getFilename, true); + return CollUtil.map(entries, LsEntry::getFilename); } /** diff --git a/hutool-extra/src/main/java/cn/hutool/extra/ssh/SshjSftp.java b/hutool-extra/src/main/java/cn/hutool/extra/ssh/SshjSftp.java index e07d08731..982c3290b 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/ssh/SshjSftp.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/ssh/SshjSftp.java @@ -157,7 +157,7 @@ public class SshjSftp extends AbstractFtp { throw new FtpException(e); } if (CollUtil.isNotEmpty(infoList)) { - return CollUtil.map(infoList, RemoteResourceInfo::getName, true); + return CollUtil.map(infoList, RemoteResourceInfo::getName); } return null; }