diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/CollectorUtil.java b/hutool-core/src/main/java/cn/hutool/core/stream/CollectorUtil.java index 14ffe6b6c..1dcc72096 100644 --- a/hutool-core/src/main/java/cn/hutool/core/stream/CollectorUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/stream/CollectorUtil.java @@ -5,10 +5,7 @@ import cn.hutool.core.text.StrUtil; import cn.hutool.core.util.ArrayUtil; import java.util.*; -import java.util.function.BiConsumer; -import java.util.function.BinaryOperator; -import java.util.function.Function; -import java.util.function.Supplier; +import java.util.function.*; import java.util.stream.Collector; import java.util.stream.Collectors; @@ -371,4 +368,131 @@ public class CollectorUtil { public static Collector, ?, Map> entryToMap() { return toMap(Map.Entry::getKey, Map.Entry::getValue); } + + /** + *

将集合转换为树,默认用 {@code parentId == null} 来判断树的根节点 + * 因为需要在当前传入数据里查找,所以这是一个结束操作
+ * + * @param idGetter id的getter对应的lambda,可以写作 {@code Student::getId} + * @param pIdGetter parentId的getter对应的lambda,可以写作 {@code Student::getParentId} + * @param childrenSetter children的setter对应的lambda,可以写作{ @code Student::setChildren} + * @param isParallel 是否并行去组装,数据量特别大时使用 + * @param 此处是元素类型 + * @param 此处是id、parentId的泛型限制 + * @return list 组装好的树
+ * eg: + *

{@code
+	 * List studentTree = students.stream().collect(toTree(Student::getId, Student::getParentId, Student::setChildren, isParallel));
+	 * }
+ */ + public static , T> Collector> toTree( + final Function idGetter, + final Function pIdGetter, + final BiConsumer> childrenSetter, + final boolean isParallel) { + return toTree(idGetter, pIdGetter, null, childrenSetter, isParallel); + } + + /** + *

将集合转换为树,默认用 {@code parentId == pidValue} 来判断树的根节点,可以为null + * 因为需要在当前传入数据里查找,所以这是一个结束操作
+ * + * @param idGetter id的getter对应的lambda,可以写作 {@code Student::getId} + * @param pIdGetter parentId的getter对应的lambda,可以写作 {@code Student::getParentId} + * @param pidValue pid的值 + * @param childrenSetter children的setter对应的lambda,可以写作{ @code Student::setChildren} + * @param isParallel 是否并行去组装,数据量特别大时使用 + * @param 此处是元素类型 + * @param 此处是id、parentId的泛型限制 + * @return list 组装好的树
+ * eg: + *

{@code
+	 * List studentTree = students.stream().collect(toTree(Student::getId, Student::getParentId, 0L, Student::setChildren, isParallel));
+	 * }
+ * @author VampireAchao + */ + public static , T> Collector> toTree( + final Function idGetter, + final Function pIdGetter, + final R pidValue, + final BiConsumer> childrenSetter, + final boolean isParallel) { + return Collectors.collectingAndThen(groupingBy(pIdGetter, Collectors.toList()), + getChildrenFromMapByPidAndSet(idGetter, pIdValuesMap -> pIdValuesMap.get(pidValue), childrenSetter, isParallel)); + } + + /** + * 将集合转换为树,自定义根节点的判断条件 + * 因为需要在当前传入数据里查找,所以这是一个结束操作 + * + * @param idGetter id的getter对应的lambda,可以写作 {@code Student::getId} + * @param pIdGetter parentId的getter对应的lambda,可以写作 {@code Student::getParentId} + * @param childrenSetter children的setter对应的lambda,可以写作 {@code Student::setChildren} + * @param parentPredicate 树顶部的判断条件,可以写作 {@code s -> Objects.equals(s.getParentId(),0L) } + * @param isParallel 是否并行处理 + * @param 此处是元素类型 + * @param 此处是id、parentId的泛型限制 + * @return list 组装好的树
+ * eg: + *
{@code
+	 * List studentTree = EasyStream.of(students).
+	 * 	.toTree(Student::getId, Student::getParentId, Student::setChildren, Student::getMatchParent);
+	 * }
+ * @author VampireAchao + */ + public static , T> Collector> toTree( + final Function idGetter, + final Function pIdGetter, + final BiConsumer> childrenSetter, + final Predicate parentPredicate, + final boolean isParallel) { + final List parents = new ArrayList<>(); + return Collectors.collectingAndThen(groupingBy(pIdGetter, + new SimpleCollector<>(ArrayList::new, + (acc, e) -> { + if (parentPredicate.test(e)) { + parents.add(e); + } + if (idGetter.apply(e) != null) { + acc.add(e); + } + }, + (left, right) -> { + left.addAll(right); + return left; + }, + CH_ID)), + getChildrenFromMapByPidAndSet(idGetter, pIdValuesMap -> parents, childrenSetter, isParallel)); + } + + /** + * toTree的内联函数 + * 因为需要在当前传入数据里查找,所以这是一个结束操作 + * + * @param idGetter id的getter对应的lambda,可以写作 {@code Student::getId} + * @param parentFactory 顶部数据工厂方法 + * @param childrenSetter children的setter对应的lambda,可以写作 {@code Student::setChildren} + * @param isParallel 是否并行处理 + * @param 此处是元素类型 + * @param 此处是id的泛型限制 + * @return list 组装好的树 + * @author VampireAchao + */ + private static , T> Function>, List> getChildrenFromMapByPidAndSet( + final Function idGetter, + final Function>, List> parentFactory, + final BiConsumer> childrenSetter, + final boolean isParallel) { + return pIdValuesMap -> { + EasyStream.of(pIdValuesMap.values(), isParallel).flat(Function.identity()) + .forEach(value -> { + final List children = pIdValuesMap.get(idGetter.apply(value)); + if (children != null) { + childrenSetter.accept(value, children); + } + }); + return parentFactory.apply(pIdValuesMap); + }; + } + } diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java index 90de48122..b892b7199 100644 --- a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java +++ b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java @@ -1,12 +1,10 @@ package cn.hutool.core.stream; import cn.hutool.core.lang.Opt; -import cn.hutool.core.lang.mutable.MutableObj; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ObjUtil; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.Spliterator; import java.util.function.*; @@ -266,91 +264,6 @@ public class EasyStream extends AbstractEnhancedWrappedStream(stream); } - /** - *

将集合转换为树,默认用 {@code parentId == null} 作为顶部,内置一个小递归 - * 因为需要在当前传入数据里查找,所以这是一个结束操作
- * - * @param idGetter id的getter对应的lambda,可以写作 {@code Student::getId} - * @param pIdGetter parentId的getter对应的lambda,可以写作 {@code Student::getParentId} - * @param childrenSetter children的setter对应的lambda,可以写作{ @code Student::setChildren} - * @param 此处是id、parentId的泛型限制 - * @return list 组装好的树
- * eg: - *

{@code
-	 * List studentTree = EasyStream.of(students).
-	 * 	toTree(Student::getId, Student::getParentId, Student::setChildren);
-	 * }
- */ - public > List toTree( - final Function idGetter, - final Function pIdGetter, - final BiConsumer> childrenSetter) { - final Map> pIdValuesMap = group(pIdGetter); - return getChildrenFromMapByPidAndSet(idGetter, childrenSetter, pIdValuesMap, pIdValuesMap.get(null)); - } - - /** - * 将集合转换为树,自定义树顶部的判断条件,内置一个小递归(没错,lambda可以写递归) - * 因为需要在当前传入数据里查找,所以这是一个结束操作 - * - * @param idGetter id的getter对应的lambda,可以写作 {@code Student::getId} - * @param pIdGetter parentId的getter对应的lambda,可以写作 {@code Student::getParentId} - * @param childrenSetter children的setter对应的lambda,可以写作 {@code Student::setChildren} - * @param parentPredicate 树顶部的判断条件,可以写作 {@code s -> Objects.equals(s.getParentId(),0L) } - * @param 此处是id、parentId的泛型限制 - * @return list 组装好的树
- * eg: - *
{@code
-	 * List studentTree = EasyStream.of(students).
-	 * 	.toTree(Student::getId, Student::getParentId, Student::setChildren, Student::getMatchParent);
-	 * }
- */ - - public > List toTree( - final Function idGetter, - final Function pIdGetter, - final BiConsumer> childrenSetter, - final Predicate parentPredicate) { - Objects.requireNonNull(parentPredicate); - final List list = toList(); - final List parents = EasyStream.of(list).filter(e -> - // 此处是为了适配 parentPredicate.test空指针 情况 - // 因为Predicate.test的返回值是boolean,所以如果 e -> null 这种返回null的情况,会直接抛出NPE - Opt.ofTry(() -> parentPredicate.test(e)).filter(Boolean::booleanValue).isPresent()) - .toList(); - return getChildrenFromMapByPidAndSet(idGetter, childrenSetter, EasyStream.of(list).group(pIdGetter), parents); - } - - /** - * toTree的内联函数,内置一个小递归(没错,lambda可以写递归) - * 因为需要在当前传入数据里查找,所以这是一个结束操作 - * - * @param idGetter id的getter对应的lambda,可以写作 {@code Student::getId} - * @param childrenSetter children的setter对应的lambda,可以写作 {@code Student::setChildren} - * @param pIdValuesMap parentId和值组成的map,用来降低复杂度 - * @param parents 顶部数据 - * @param 此处是id的泛型限制 - * @return list 组装好的树 - */ - private > List getChildrenFromMapByPidAndSet( - final Function idGetter, - final BiConsumer> childrenSetter, - final Map> pIdValuesMap, - final List parents) { - Objects.requireNonNull(idGetter); - Objects.requireNonNull(childrenSetter); - Objects.requireNonNull(pIdValuesMap); - final MutableObj>> recursiveRef = new MutableObj<>(); - final Consumer> recursive = values -> EasyStream.of(values, isParallel()).forEach(value -> { - final List children = pIdValuesMap.get(idGetter.apply(value)); - childrenSetter.accept(value, children); - recursiveRef.get().accept(children); - }); - recursiveRef.set(recursive); - recursive.accept(parents); - return parents; - } - /** * 建造者 * diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/TerminableWrappedStream.java b/hutool-core/src/main/java/cn/hutool/core/stream/TerminableWrappedStream.java index e329f9901..19958f0c4 100644 --- a/hutool-core/src/main/java/cn/hutool/core/stream/TerminableWrappedStream.java +++ b/hutool-core/src/main/java/cn/hutool/core/stream/TerminableWrappedStream.java @@ -22,47 +22,47 @@ import java.util.stream.Stream; */ public interface TerminableWrappedStream> extends WrappedStream { - // region ============ to collection ============ + // region ============ to collection ============ - /** - * 转换为{@link ArrayList} - * - * @return 集合 - * @see #toColl(Supplier) - */ - default List toList() { - return this.toColl(ArrayList::new); - } - - /** - * 换为不可变集合 - * - * @return 集合 + /** + * 转换为{@link ArrayList} + * + * @return 集合 * @see #toColl(Supplier) */ - default List toUnmodifiableList() { - return Collections.unmodifiableList(this.toList()); - } + default List toList() { + return this.toColl(ArrayList::new); + } - /** - * 转换为HashSet - * - * @return 集合 + /** + * 换为不可变集合 + * + * @return 集合 * @see #toColl(Supplier) */ - default Set toSet() { - return this.toColl(HashSet::new); - } + default List toUnmodifiableList() { + return Collections.unmodifiableList(this.toList()); + } - /** - * 换为不可变集合 - * - * @return 集合 + /** + * 转换为HashSet + * + * @return 集合 * @see #toColl(Supplier) */ - default Set toUnmodifiableSet() { - return Collections.unmodifiableSet(this.toSet()); - } + default Set toSet() { + return this.toColl(HashSet::new); + } + + /** + * 换为不可变集合 + * + * @return 集合 + * @see #toColl(Supplier) + */ + default Set toUnmodifiableSet() { + return Collections.unmodifiableSet(this.toSet()); + } /** * 转换成集合 @@ -76,103 +76,103 @@ public interface TerminableWrappedStream key类型 - * @return map + /** + * 转换为map,key为给定操作执行后的返回值,value为当前元素 + * + * @param keyMapper 指定的key操作 + * @param key类型 + * @return map * @see #toMap(Function, Function, BinaryOperator, Supplier) - */ - default Map toMap(final Function keyMapper) { - return this.toMap(keyMapper, Function.identity()); - } + */ + default Map toMap(final Function keyMapper) { + return this.toMap(keyMapper, Function.identity()); + } - /** - * 转换为map,key,value为给定操作执行后的返回值 - * - * @param keyMapper 指定的key操作 - * @param valueMapper 指定value操作 - * @param key类型 - * @param value类型 - * @return map + /** + * 转换为map,key,value为给定操作执行后的返回值 + * + * @param keyMapper 指定的key操作 + * @param valueMapper 指定value操作 + * @param key类型 + * @param value类型 + * @return map * @see #toMap(Function, Function, BinaryOperator, Supplier) - */ - default Map toMap( - final Function keyMapper, final Function valueMapper) { - return this.toMap(keyMapper, valueMapper, (l, r) -> r); - } + */ + default Map toMap( + final Function keyMapper, final Function valueMapper) { + return this.toMap(keyMapper, valueMapper, (l, r) -> r); + } - /** - * 转换为不可变map,key,value为给定操作执行后的返回值 - * - * @param keyMapper 指定的key操作 - * @param valueMapper 指定value操作 - * @param key类型 - * @param value类型 - * @return map + /** + * 转换为不可变map,key,value为给定操作执行后的返回值 + * + * @param keyMapper 指定的key操作 + * @param valueMapper 指定value操作 + * @param key类型 + * @param value类型 + * @return map * @see #toMap(Function, Function, BinaryOperator, Supplier) - */ - default Map toUnmodifiableMap( - final Function keyMapper, final Function valueMapper) { - return Collections.unmodifiableMap(this.toMap(keyMapper, valueMapper)); - } + */ + default Map toUnmodifiableMap( + final Function keyMapper, final Function valueMapper) { + return Collections.unmodifiableMap(this.toMap(keyMapper, valueMapper)); + } - /** - * 转换为map,key,value为给定操作执行后的返回值 - * - * @param keyMapper 指定的key操作 - * @param valueMapper 指定value操作 - * @param mergeFunction 合并操作 - * @param key类型 - * @param value类型 - * @return map + /** + * 转换为map,key,value为给定操作执行后的返回值 + * + * @param keyMapper 指定的key操作 + * @param valueMapper 指定value操作 + * @param mergeFunction 合并操作 + * @param key类型 + * @param value类型 + * @return map * @see #toMap(Function, Function, BinaryOperator, Supplier) - */ - default Map toMap( - final Function keyMapper, - final Function valueMapper, - final BinaryOperator mergeFunction) { - return this.toMap(keyMapper, valueMapper, mergeFunction, HashMap::new); - } + */ + default Map toMap( + final Function keyMapper, + final Function valueMapper, + final BinaryOperator mergeFunction) { + return this.toMap(keyMapper, valueMapper, mergeFunction, HashMap::new); + } - /** - * 转换为不可变map,key,value为给定操作执行后的返回值 - * - * @param keyMapper 指定的key操作 - * @param valueMapper 指定value操作 - * @param mergeFunction 合并操作 - * @param key类型 - * @param value类型 - * @return map + /** + * 转换为不可变map,key,value为给定操作执行后的返回值 + * + * @param keyMapper 指定的key操作 + * @param valueMapper 指定value操作 + * @param mergeFunction 合并操作 + * @param key类型 + * @param value类型 + * @return map * @see #toMap(Function, Function, BinaryOperator, Supplier) - */ - default Map toUnmodifiableMap( - final Function keyMapper, - final Function valueMapper, - final BinaryOperator mergeFunction) { - return Collections.unmodifiableMap( - this.toMap(keyMapper, valueMapper, mergeFunction, HashMap::new) + */ + default Map toUnmodifiableMap( + final Function keyMapper, + final Function valueMapper, + final BinaryOperator mergeFunction) { + return Collections.unmodifiableMap( + this.toMap(keyMapper, valueMapper, mergeFunction, HashMap::new) ); - } + } - /** - * 转换为map,key,value为给定操作执行后的返回值 - * - * @param keyMapper 指定的key操作 - * @param valueMapper 指定value操作 - * @param mergeFunction 合并操作 - * @param mapSupplier map工厂 - * @param key类型 - * @param value类型 - * @param map类型 - * @return map - */ - default > M toMap( + /** + * 转换为map,key,value为给定操作执行后的返回值 + * + * @param keyMapper 指定的key操作 + * @param valueMapper 指定value操作 + * @param mergeFunction 合并操作 + * @param mapSupplier map工厂 + * @param key类型 + * @param value类型 + * @param map类型 + * @return map + */ + default > M toMap( final Function keyMapper, final Function valueMapper, final BinaryOperator mergeFunction, @@ -181,40 +181,89 @@ public interface TerminableWrappedStream将集合转换为树,默认用 {@code parentId == null} 来判断树的根节点 + * 因为需要在当前传入数据里查找,所以这是一个结束操作
+ * + * @param idGetter id的getter对应的lambda,可以写作 {@code Student::getId} + * @param pIdGetter parentId的getter对应的lambda,可以写作 {@code Student::getParentId} + * @param childrenSetter children的setter对应的lambda,可以写作{ @code Student::setChildren} + * @param 此处是id、parentId的泛型限制 + * @return list 组装好的树
+ * eg: + *
{@code
+	 * List studentTree = EasyStream.of(students).
+	 * 	toTree(Student::getId, Student::getParentId, Student::setChildren);
+	 * }
+ * @author VampireAchao + */ + default > List toTree( + final Function idGetter, + final Function pIdGetter, + final BiConsumer> childrenSetter) { + return collect(CollectorUtil.toTree(idGetter, pIdGetter, childrenSetter, isParallel())); + } - // region ============ to zip ============ + /** + * 将集合转换为树,自定义根节点的判断条件 + * 因为需要在当前传入数据里查找,所以这是一个结束操作 + * + * @param idGetter id的getter对应的lambda,可以写作 {@code Student::getId} + * @param pIdGetter parentId的getter对应的lambda,可以写作 {@code Student::getParentId} + * @param childrenSetter children的setter对应的lambda,可以写作 {@code Student::setChildren} + * @param parentPredicate 树顶部的判断条件,可以写作 {@code s -> Objects.equals(s.getParentId(),0L) } + * @param 此处是id、parentId的泛型限制 + * @return list 组装好的树
+ * eg: + *
{@code
+	 * List studentTree = EasyStream.of(students).
+	 * 	.toTree(Student::getId, Student::getParentId, Student::setChildren, Student::getMatchParent);
+	 * }
+ * @author VampireAchao + */ + default > List toTree( + final Function idGetter, + final Function pIdGetter, + final BiConsumer> childrenSetter, + final Predicate parentPredicate) { + return collect(CollectorUtil.toTree(idGetter, pIdGetter, childrenSetter, parentPredicate, isParallel())); + } - /** - * 与给定的可迭代对象转换成map,key为现有元素,value为给定可迭代对象迭代的元素
- * 至少包含全部的key,如果对应位置上的value不存在,则为null - * - * @param other 可迭代对象 - * @param 可迭代对象迭代的元素类型 - * @return map,key为现有元素,value为给定可迭代对象迭代的元素;
- * 至少包含全部的key,如果对应位置上的value不存在,则为null;
- * 如果key重复, 则保留最后一个关联的value;
- */ - default Map toZip(final Iterable other) { + + // endregion + + // region ============ to zip ============ + + /** + * 与给定的可迭代对象转换成map,key为现有元素,value为给定可迭代对象迭代的元素
+ * 至少包含全部的key,如果对应位置上的value不存在,则为null + * + * @param other 可迭代对象 + * @param 可迭代对象迭代的元素类型 + * @return map,key为现有元素,value为给定可迭代对象迭代的元素;
+ * 至少包含全部的key,如果对应位置上的value不存在,则为null;
+ * 如果key重复, 则保留最后一个关联的value;
+ */ + default Map toZip(final Iterable other) { Objects.requireNonNull(other); - // value对象迭代器 - final Iterator iterator = Opt.ofNullable(other).map(Iterable::iterator).orElseGet(Collections::emptyIterator); - if (this.isParallel()) { + // value对象迭代器 + final Iterator iterator = Opt.ofNullable(other).map(Iterable::iterator).orElseGet(Collections::emptyIterator); + if (this.isParallel()) { final List keyList = toList(); - final Map map = new HashMap<>(keyList.size()); - for (final T key : keyList) { - map.put(key, iterator.hasNext() ? iterator.next() : null); - } - return map; - } else { - return this.toMap(Function.identity(), e -> iterator.hasNext() ? iterator.next() : null); - } - } + final Map map = new HashMap<>(keyList.size()); + for (final T key : keyList) { + map.put(key, iterator.hasNext() ? iterator.next() : null); + } + return map; + } else { + return this.toMap(Function.identity(), e -> iterator.hasNext() ? iterator.next() : null); + } + } - // endregion + // endregion // region ============ to optional ============ @@ -408,7 +457,7 @@ public interface TerminableWrappedStream Map group( - final Function classifier, final Collector downstream) { + final Function classifier, final Collector downstream) { return this.group(classifier, HashMap::new, downstream); } @@ -426,9 +475,9 @@ public interface TerminableWrappedStream> M group( - final Function classifier, - final Supplier mapFactory, - final Collector downstream) { + final Function classifier, + final Supplier mapFactory, + final Collector downstream) { Objects.requireNonNull(classifier); Objects.requireNonNull(mapFactory); Objects.requireNonNull(downstream); @@ -449,8 +498,8 @@ public interface TerminableWrappedStream 值类型 - * @param predicate 判断条件 + * @param 值类型 + * @param predicate 判断条件 * @param collFactory 提供的集合 * @return map * @see #partition(Predicate, Collector) @@ -464,7 +513,7 @@ public interface TerminableWrappedStream 返回值类型 + * @param 返回值类型 * @return map */ default Map partition(final Predicate predicate, final Collector downstream) { diff --git a/hutool-core/src/test/java/cn/hutool/core/stream/AbstractEnhancedWrappedStreamTest.java b/hutool-core/src/test/java/cn/hutool/core/stream/AbstractEnhancedWrappedStreamTest.java index 8935a75ad..be03d08bd 100644 --- a/hutool-core/src/test/java/cn/hutool/core/stream/AbstractEnhancedWrappedStreamTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/stream/AbstractEnhancedWrappedStreamTest.java @@ -40,7 +40,7 @@ public class AbstractEnhancedWrappedStreamTest { @Test public void testToSet() { final List list = asList(1, 2, 3); - Set toSet = wrap(list).map(String::valueOf).toSet(); + final Set toSet = wrap(list).map(String::valueOf).toSet(); Assert.assertEquals(new HashSet<>(asList("1", "2", "3")), toSet); } @@ -636,7 +636,7 @@ public class AbstractEnhancedWrappedStreamTest { List zip = wrap(orders).zip(list, (e1, e2) -> e1 + "." + e2).toList(); Assert.assertEquals(Arrays.asList("1.dromara", "2.hutool", "3.sweet"), zip); - zip = wrap((Stream) EasyStream.iterate(1, i -> i + 1)).limit(10).zip(list, (e1, e2) -> e1 + "." + e2).toList(); + zip = this.wrap((Stream)EasyStream.iterate(1, i -> i + 1)).limit(10).zip(list, (e1, e2) -> e1 + "." + e2).toList(); Assert.assertEquals(Arrays.asList("1.dromara", "2.hutool", "3.sweet"), zip); } @@ -663,15 +663,15 @@ public class AbstractEnhancedWrappedStreamTest { } @SafeVarargs - private static Wrapper wrap(T... array) { + private final Wrapper wrap(final T... array) { return new Wrapper<>(Stream.of(array)); } - private static Wrapper wrap(Iterable iterable) { + private Wrapper wrap(final Iterable iterable) { return new Wrapper<>(StreamSupport.stream(iterable.spliterator(), false)); } - private static Wrapper wrap(Stream stream) { + private Wrapper wrap(final Stream stream) { return new Wrapper<>(stream); } @@ -683,12 +683,12 @@ public class AbstractEnhancedWrappedStreamTest { * @param stream 包装的流对象 * @throws NullPointerException 当{@code unwrap}为{@code null}时抛出 */ - protected Wrapper(Stream stream) { + protected Wrapper(final Stream stream) { super(stream); } @Override - public Wrapper wrap(Stream source) { + public Wrapper wrap(final Stream source) { return new Wrapper<>(source); } diff --git a/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java b/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java index 26fa81ef8..166a3f201 100644 --- a/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java @@ -2,6 +2,7 @@ package cn.hutool.core.stream; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.BooleanUtil; import lombok.Data; import lombok.experimental.Tolerate; import org.junit.Assert; @@ -181,7 +182,7 @@ public class EasyStreamTest { Assert.assertEquals(collect2, distinctBy2); Assert.assertEquals( - 4, EasyStream.of(1, 2, 2, null, 3, null).parallel(true).distinct(t -> Objects.isNull(t) ? null : t.toString()).sequential().count() + 4, EasyStream.of(1, 2, 2, null, 3, null).parallel(true).distinct(t -> Objects.isNull(t) ? null : t.toString()).sequential().count() ); } @@ -476,7 +477,7 @@ public class EasyStreamTest { Student.builder().id(8L).name("jobob").parentId(5L).build() ) // just 4 lambda ,top by condition - .toTree(Student::getId, Student::getParentId, Student::setChildren, Student::getMatchParent); + .toTree(Student::getId, Student::getParentId, Student::setChildren, s -> BooleanUtil.isTrue(s.getMatchParent())); Assert.assertEquals(asList( Student.builder().id(1L).name("dromara").matchParent(true) .children(asList(Student.builder().id(3L).name("hutool").parentId(1L) @@ -540,7 +541,7 @@ public class EasyStreamTest { private Long id; private Long parentId; private List children; - private Boolean matchParent = false; + private Boolean matchParent; @Tolerate public Student() {