From 492a281cf92e9a5d4c5dc0d954cd6a0cdb169b17 Mon Sep 17 00:00:00 2001 From: VampireAchao Date: Fri, 9 Sep 2022 14:38:28 +0800 Subject: [PATCH 1/4] =?UTF-8?q?:trollface:=20=E5=A2=9E=E5=BC=BAEasyStream#?= =?UTF-8?q?zip=E5=AF=B9=E5=B9=B6=E8=A1=8C=E6=B5=81=E7=9A=84=E6=94=AF?= =?UTF-8?q?=E6=8C=81=EF=BC=8C=E6=8F=90=E4=BE=9BCollectorUtil.entryToMap?= =?UTF-8?q?=E5=AF=B9Entry=E8=BD=ACmap=E6=8F=90=E4=BE=9B=E6=94=AF=E6=8C=81?= =?UTF-8?q?=EF=BC=8C=E5=AE=8C=E5=96=84javadoc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/hutool/core/stream/CollectorUtil.java | 20 +- .../core/stream/TerminableWrappedStream.java | 311 +++++++++--------- .../stream/TransformableWrappedStream.java | 49 ++- .../AbstractEnhancedWrappedStreamTest.java | 122 +++---- 4 files changed, 252 insertions(+), 250 deletions(-) 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 94a55651f..14ffe6b6c 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 @@ -134,7 +134,7 @@ public class CollectorUtil { * @return {@link Collector} */ public static Collector> groupingBy(final Function classifier, - final Collector downstream) { + final Collector downstream) { return groupingBy(classifier, HashMap::new, downstream); } @@ -273,14 +273,14 @@ public class CollectorUtil { /** * 将流转为{@link EntryStream} * - * @param keyMapper 键的映射方法 - * @param 输入元素类型 - * @param 元素的键类型 + * @param keyMapper 键的映射方法 + * @param 输入元素类型 + * @param 元素的键类型 * @return 收集器 * @since 6.0.0 */ public static Collector, EntryStream> toEntryStream( - Function keyMapper) { + Function keyMapper) { return toEntryStream(keyMapper, Function.identity()); } @@ -361,4 +361,14 @@ public class CollectorUtil { return transform(ArrayList::new, mapper); } + /** + * 用于{@code Stream} 转 Map 的情况 + * + * @param key类型 + * @param value类型 + * @return map + */ + public static Collector, ?, Map> entryToMap() { + return toMap(Map.Entry::getKey, Map.Entry::getValue); + } } 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 d2a09ef7b..ba5f73f47 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 @@ -17,52 +17,52 @@ import java.util.stream.Stream; * * @param 流中的元素类型 * @param {@link TerminableWrappedStream}的实现类类型 - * @author huangchengxing + * @author huangchengxing VampireAchao * @since 6.0.0 */ 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,145 +76,145 @@ 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( - final Function keyMapper, - final Function valueMapper, - final BinaryOperator mergeFunction, - Supplier mapSupplier) { + /** + * 转换为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, + Supplier mapSupplier) { Objects.requireNonNull(keyMapper); Objects.requireNonNull(valueMapper); Objects.requireNonNull(mergeFunction); Objects.requireNonNull(mapSupplier); - return unwrap().collect(Collectors.toMap(keyMapper, valueMapper, mergeFunction, mapSupplier)); - } + return unwrap().collect(Collectors.toMap(keyMapper, valueMapper, mergeFunction, mapSupplier)); + } - // endregion + // endregion - // region ============ to zip ============ + // 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) { + /** + * 与给定的可迭代对象转换成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 (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 (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 +408,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 +426,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 +449,9 @@ public interface TerminableWrappedStream 集合类型 * @return map * @see #partition(Predicate, Collector) */ @@ -463,7 +464,7 @@ public interface TerminableWrappedStream 返回值类型 + * @param 返回值类型 * @return map */ default Map partition(final Predicate predicate, final Collector downstream) { diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/TransformableWrappedStream.java b/hutool-core/src/main/java/cn/hutool/core/stream/TransformableWrappedStream.java index b689db3fa..698005ca8 100644 --- a/hutool-core/src/main/java/cn/hutool/core/stream/TransformableWrappedStream.java +++ b/hutool-core/src/main/java/cn/hutool/core/stream/TransformableWrappedStream.java @@ -3,7 +3,6 @@ package cn.hutool.core.stream; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.collection.iter.IterUtil; import cn.hutool.core.lang.Console; -import cn.hutool.core.lang.Opt; import cn.hutool.core.lang.mutable.MutableInt; import cn.hutool.core.lang.mutable.MutableObj; import cn.hutool.core.map.MapUtil; @@ -24,7 +23,7 @@ import java.util.stream.StreamSupport; * * @param 流中的元素类型 * @param {@link TransformableWrappedStream}的实现类类型 - * @author huangchengxing + * @author huangchengxing VampireAchao * @since 6.0.0 */ public interface TransformableWrappedStream> extends WrappedStream { @@ -40,24 +39,15 @@ public interface TransformableWrappedStream EasyStream zip( - final Iterable other, - final BiFunction zipper) { + final Iterable other, + final BiFunction zipper) { Objects.requireNonNull(zipper); - final Spliterator keys = spliterator(); - final Spliterator values = Opt.ofNullable(other).map(Iterable::spliterator).orElseGet(Spliterators::emptySpliterator); - // 获取两个Spliterator的中较小的数量 - // 如果Spliterator经过流操作, getExactSizeIfKnown()可能会返回-1, 所以默认大小为 ArrayList.DEFAULT_CAPACITY - final int sizeIfKnown = (int) Math.max(Math.min(keys.getExactSizeIfKnown(), values.getExactSizeIfKnown()), 10); - final List list = new ArrayList<>(sizeIfKnown); - // 保存第一个Spliterator的值 - final MutableObj key = new MutableObj<>(); - // 保存第二个Spliterator的值 - final MutableObj value = new MutableObj<>(); - // 当两个Spliterator中都还有剩余元素时 - while (keys.tryAdvance(key::set) && values.tryAdvance(value::set)) { - list.add(zipper.apply(key.get(), value.get())); + Map idxIdentityMap = mapIdx((e, idx) -> MapUtil.entry(idx, e)).collect(CollectorUtil.entryToMap()); + Map idxOtherMap = EasyStream.of(other).mapIdx((e, idx) -> MapUtil.entry(idx, e)).collect(CollectorUtil.entryToMap()); + if (idxIdentityMap.size() <= idxOtherMap.size()) { + return EasyStream.of(idxIdentityMap.keySet(), isParallel()).map(k -> zipper.apply(idxIdentityMap.get(k), idxOtherMap.get(k))); } - return EasyStream.of(list).parallel(isParallel()).onClose(unwrap()::close); + return EasyStream.of(idxOtherMap.keySet(), isParallel()).map(k -> zipper.apply(idxIdentityMap.get(k), idxOtherMap.get(k))); } /** @@ -78,9 +68,9 @@ public interface TransformableWrappedStream>of(EasyStream.of(list, isParallel())); } return EasyStream.iterate(0, i -> i < size, i -> i + batchSize) - .map(skip -> EasyStream.of(list.subList(skip, Math.min(size, skip + batchSize)), isParallel())) - .parallel(isParallel()) - .onClose(unwrap()::close); + .map(skip -> EasyStream.of(list.subList(skip, Math.min(size, skip + batchSize)), isParallel())) + .parallel(isParallel()) + .onClose(unwrap()::close); } /** @@ -114,8 +104,8 @@ public interface TransformableWrappedStream 键类型 + * @param keyMapper 键的映射方法 + * @param 键类型 * @return {@link EntryStream}实例 */ default EntryStream toEntries(final Function keyMapper) { @@ -158,7 +148,7 @@ public interface TransformableWrappedStream elements = unwrap().collect(Collectors.toList()); return wrap(ListUtil.splice(elements, start, deleteCount, items).stream()) - .parallel(isParallel()); + .parallel(isParallel()); } /** @@ -191,15 +181,15 @@ public interface TransformableWrappedStream删除流中与断言匹配的元素,当遇到第一个不匹配的元素时终止,返回由剩余不匹配的元素组成的流。
+ * 删除流中与断言匹配的元素,当遇到第一个不匹配的元素时终止,返回由剩余不匹配的元素组成的流。 * eg: *
{@code
 	 * EasyStream.of(1, 2, 3, 4, 5)
 	 * 	.dropWhile(i -> !Objects.equals(3, i)) // 删除不为3的元素,一直到遇到第一个3为止
 	 * 	.toList(); // = [3, 4, 5]
 	 * }
- * - *

与{@code JDK9}中的{@code dropWhile}方法不太一样,此操作为顺序且有状态的中间操作。 + *

+ * 与{@code JDK9}中的{@code dropWhile}方法不太一样,此操作为顺序且有状态的中间操作。 * 即使在并行流中,该操作仍然是顺序执行的,并且不影响后续的并行操作: *

{@code
 	 * EasyStream.iterate(1, i -> i + 1)
@@ -261,6 +251,7 @@ public interface TransformableWrappedStream>> recursiveRef = new MutableObj<>();
 		final Function> recursive = e -> EasyStream.of(childrenGetter.apply(e))
-			.flat(recursiveRef.get())
-			.unshift(e);
+				.flat(recursiveRef.get())
+				.unshift(e);
 		recursiveRef.set(recursive);
 		return wrap(flatMap(recursive).peek(e -> childrenSetter.accept(e, null)));
 	}
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 6922d30b5..12d8e1197 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
@@ -33,7 +33,7 @@ public class AbstractEnhancedWrappedStreamTest {
 	@Test
 	public void testToUnmodifiableList() {
 		final List list = wrap(1, 2, 3)
-			.toUnmodifiableList();
+				.toUnmodifiableList();
 		Assert.assertThrows(UnsupportedOperationException.class, () -> list.remove(0));
 	}
 
@@ -47,7 +47,7 @@ public class AbstractEnhancedWrappedStreamTest {
 	@Test
 	public void testToUnmodifiableSet() {
 		final Set set = wrap(1, 2, 3)
-			.toUnmodifiableSet();
+				.toUnmodifiableSet();
 		Assert.assertThrows(UnsupportedOperationException.class, () -> set.remove(0));
 	}
 
@@ -98,8 +98,8 @@ public class AbstractEnhancedWrappedStreamTest {
 	@Test
 	public void testFindFirst() {
 		final List list = asList(1, 2, 3);
-		Assert.assertEquals((Integer)1, wrap(list).findFirst(t -> (t & 1) == 1).orElse(null));
-		Assert.assertEquals((Integer)1, wrap(list).filter(t -> (t & 1) == 1).findFirst().orElse(null));
+		Assert.assertEquals((Integer) 1, wrap(list).findFirst(t -> (t & 1) == 1).orElse(null));
+		Assert.assertEquals((Integer) 1, wrap(list).filter(t -> (t & 1) == 1).findFirst().orElse(null));
 	}
 
 	@Test
@@ -111,7 +111,7 @@ public class AbstractEnhancedWrappedStreamTest {
 	@Test
 	public void testFindLast() {
 		final List list = asList(1, 2, 3);
-		Assert.assertEquals((Integer)3, wrap(list).findLast(t -> (t & 1) == 1).orElse(null));
+		Assert.assertEquals((Integer) 3, wrap(list).findLast(t -> (t & 1) == 1).orElse(null));
 	}
 
 	@Test
@@ -123,7 +123,7 @@ public class AbstractEnhancedWrappedStreamTest {
 	@Test
 	public void testAt() {
 		final List list = asList(1, 2, 3);
-		Assert.assertEquals((Integer)3, wrap(list).at(2).orElse(null));
+		Assert.assertEquals((Integer) 3, wrap(list).at(2).orElse(null));
 	}
 
 	@Test
@@ -219,13 +219,13 @@ public class AbstractEnhancedWrappedStreamTest {
 	@Test
 	public void testMapToInt() {
 		final int[] array = wrap(1, 2, 3).mapToInt(Integer::intValue).toArray();
-		Assert.assertArrayEquals(new int[] {1, 2, 3}, array);
+		Assert.assertArrayEquals(new int[]{1, 2, 3}, array);
 	}
 
 	@Test
 	public void testMapToLong() {
 		final long[] array = wrap(1L, 2L, 3L).mapToLong(Long::intValue).toArray();
-		Assert.assertArrayEquals(new long[] {1L, 2L, 3L}, array);
+		Assert.assertArrayEquals(new long[]{1L, 2L, 3L}, array);
 	}
 
 	@Test
@@ -239,13 +239,13 @@ public class AbstractEnhancedWrappedStreamTest {
 	@Test
 	public void testFlatMapToInt() {
 		final int[] array = wrap(1, 2, 3).flatMapToInt(IntStream::of).toArray();
-		Assert.assertArrayEquals(new int[] {1, 2, 3}, array);
+		Assert.assertArrayEquals(new int[]{1, 2, 3}, array);
 	}
 
 	@Test
 	public void testFlatMapToLong() {
 		final long[] array = wrap(1L, 2L, 3L).flatMapToLong(LongStream::of).toArray();
-		Assert.assertArrayEquals(new long[] {1L, 2L, 3L}, array);
+		Assert.assertArrayEquals(new long[]{1L, 2L, 3L}, array);
 	}
 
 	@Test
@@ -312,28 +312,28 @@ public class AbstractEnhancedWrappedStreamTest {
 
 	@Test
 	public void testReduce() {
-		Assert.assertEquals((Integer)6, wrap(1, 2, 3).reduce(Integer::sum).orElse(null));
-		Assert.assertEquals((Integer)6, wrap(1, 2, 3).reduce(0, Integer::sum));
-		Assert.assertEquals((Integer)6, wrap(1, 2, 3).reduce(0, Integer::sum, Integer::sum));
+		Assert.assertEquals((Integer) 6, wrap(1, 2, 3).reduce(Integer::sum).orElse(null));
+		Assert.assertEquals((Integer) 6, wrap(1, 2, 3).reduce(0, Integer::sum));
+		Assert.assertEquals((Integer) 6, wrap(1, 2, 3).reduce(0, Integer::sum, Integer::sum));
 	}
 
 	@Test
 	public void testCollect() {
 		Assert.assertEquals(asList(1, 2, 3), wrap(1, 2, 3).collect(Collectors.toList()));
 		Assert.assertEquals(
-			asList(1, 2, 3),
-			wrap(1, 2, 3).collect(ArrayList::new, List::add, List::addAll)
+				asList(1, 2, 3),
+				wrap(1, 2, 3).collect(ArrayList::new, List::add, List::addAll)
 		);
 	}
 
 	@Test
 	public void testMin() {
-		Assert.assertEquals((Integer)1, wrap(1, 2, 3).min(Comparator.comparingInt(Integer::intValue)).orElse(null));
+		Assert.assertEquals((Integer) 1, wrap(1, 2, 3).min(Comparator.comparingInt(Integer::intValue)).orElse(null));
 	}
 
 	@Test
 	public void testMax() {
-		Assert.assertEquals((Integer)3, wrap(1, 2, 3).max(Comparator.comparingInt(Integer::intValue)).orElse(null));
+		Assert.assertEquals((Integer) 3, wrap(1, 2, 3).max(Comparator.comparingInt(Integer::intValue)).orElse(null));
 	}
 
 	@Test
@@ -377,7 +377,7 @@ public class AbstractEnhancedWrappedStreamTest {
 	public void testSpliterator() {
 		final Spliterator iter1 = Stream.of(1, 2, 3).spliterator();
 		final Spliterator iter2 = wrap(1, 2, 3).spliterator();
-			Assert.assertEquals(iter1.trySplit().estimateSize(), iter2.trySplit().estimateSize());
+		Assert.assertEquals(iter1.trySplit().estimateSize(), iter2.trySplit().estimateSize());
 	}
 
 	@Test
@@ -412,7 +412,7 @@ public class AbstractEnhancedWrappedStreamTest {
 	@Test
 	public void testReverse() {
 		Assert.assertEquals(
-			asList(3, 2, 1), wrap(1, 2, 3).reverse().toList()
+				asList(3, 2, 1), wrap(1, 2, 3).reverse().toList()
 		);
 	}
 
@@ -424,15 +424,15 @@ public class AbstractEnhancedWrappedStreamTest {
 	@Test
 	public void testSplice() {
 		Assert.assertEquals(
-			asList(1, 4, 5), wrap(1, 2, 3).splice(1, 2, 4, 5).toList()
+				asList(1, 4, 5), wrap(1, 2, 3).splice(1, 2, 4, 5).toList()
 		);
 	}
 
 	@Test
 	public void testTakeWhile() {
 		Assert.assertEquals(
-			asList(1, 2),
-			wrap(1, 2, 3, 4).takeWhile(i -> !Objects.equals(i, 3)).toList()
+				asList(1, 2),
+				wrap(1, 2, 3, 4).takeWhile(i -> !Objects.equals(i, 3)).toList()
 		);
 
 	}
@@ -440,15 +440,15 @@ public class AbstractEnhancedWrappedStreamTest {
 	@Test
 	public void testDropWhile() {
 		Assert.assertEquals(
-			asList(3, 4),
-			wrap(1, 2, 3, 4).dropWhile(i -> !Objects.equals(i, 3)).toList()
+				asList(3, 4),
+				wrap(1, 2, 3, 4).dropWhile(i -> !Objects.equals(i, 3)).toList()
 		);
 	}
 
 	@Test
 	public void testDistinct() {
 		Assert.assertEquals(
-			asList(1, 2, 3), wrap(1, 1, 2, 3).distinct().toList()
+				asList(1, 2, 3), wrap(1, 1, 2, 3).distinct().toList()
 		);
 	}
 
@@ -460,41 +460,41 @@ public class AbstractEnhancedWrappedStreamTest {
 	@Test
 	public void testPush() {
 		Assert.assertEquals(
-			asList(1, 2, 3), wrap(1).push(2, 3).toList()
+				asList(1, 2, 3), wrap(1).push(2, 3).toList()
 		);
 	}
 
 	@Test
 	public void testUnshift() {
 		Assert.assertEquals(
-			asList(1, 2, 3), wrap(3).unshift(1, 2).toList()
+				asList(1, 2, 3), wrap(3).unshift(1, 2).toList()
 		);
 	}
 
 	@Test
 	public void testAppend() {
 		Assert.assertEquals(
-			asList(1, 2, 3), wrap(1).append(asList(2, 3)).toList()
+				asList(1, 2, 3), wrap(1).append(asList(2, 3)).toList()
 		);
 		Assert.assertEquals(
-			asList(1, 2, 3), wrap(1, 2, 3).append(null).toList()
+				asList(1, 2, 3), wrap(1, 2, 3).append(null).toList()
 		);
 	}
 
 	@Test
 	public void testPrepend() {
 		Assert.assertEquals(
-			asList(1, 2, 3), wrap(3).prepend(asList(1, 2)).toList()
+				asList(1, 2, 3), wrap(3).prepend(asList(1, 2)).toList()
 		);
 		Assert.assertEquals(
-			asList(1, 2, 3), wrap(1, 2, 3).prepend(null).toList()
+				asList(1, 2, 3), wrap(1, 2, 3).prepend(null).toList()
 		);
 	}
 
 	@Test
 	public void testNonNull() {
 		Assert.assertEquals(
-			asList(1, 3), wrap(1, null, 3).nonNull().toList()
+				asList(1, 3), wrap(1, null, 3).nonNull().toList()
 		);
 	}
 
@@ -502,11 +502,11 @@ public class AbstractEnhancedWrappedStreamTest {
 	public void testFilterIdx() {
 		final List indexes = new ArrayList<>();
 		Assert.assertEquals(
-			asList(1, 3),
-			wrap(1, 2, 3).filterIdx((t, i) -> {
-				indexes.add(i);
-				return (t & 1) == 1;
-			}).toList()
+				asList(1, 3),
+				wrap(1, 2, 3).filterIdx((t, i) -> {
+					indexes.add(i);
+					return (t & 1) == 1;
+				}).toList()
 		);
 		Assert.assertEquals(asList(0, 1, 2), indexes);
 	}
@@ -514,14 +514,14 @@ public class AbstractEnhancedWrappedStreamTest {
 	@Test
 	public void testFilter() {
 		Assert.assertEquals(
-			asList(1, 3), wrap(1, 2, 3).filter(i -> (i & 1) == 1).toList()
+				asList(1, 3), wrap(1, 2, 3).filter(i -> (i & 1) == 1).toList()
 		);
 	}
 
 	@Test
 	public void testFlatMap() {
 		Assert.assertEquals(
-			asList(1, 2, 3), wrap(1, 2, 3).flatMap(Stream::of).toList()
+				asList(1, 2, 3), wrap(1, 2, 3).flatMap(Stream::of).toList()
 		);
 	}
 
@@ -529,10 +529,10 @@ public class AbstractEnhancedWrappedStreamTest {
 	public void testFlatMapIdx() {
 		final List indexes = new ArrayList<>();
 		Assert.assertEquals(
-			asList(1, 2, 3), wrap(1, 2, 3).flatMapIdx((t, i) -> {
-				indexes.add(i);
-				return Stream.of(t);
-			}).toList()
+				asList(1, 2, 3), wrap(1, 2, 3).flatMapIdx((t, i) -> {
+					indexes.add(i);
+					return Stream.of(t);
+				}).toList()
 		);
 		Assert.assertEquals(asList(0, 1, 2), indexes);
 	}
@@ -540,14 +540,14 @@ public class AbstractEnhancedWrappedStreamTest {
 	@Test
 	public void testFlat() {
 		Assert.assertEquals(
-			asList(1, 2, 3), wrap(1, 2, 3).flat(Collections::singletonList).toList()
+				asList(1, 2, 3), wrap(1, 2, 3).flat(Collections::singletonList).toList()
 		);
 	}
 
 	@Test
 	public void testFlatNonNull() {
 		Assert.assertEquals(
-			asList(2, 3), wrap(null, 2, 3).flatNonNull(Collections::singletonList).toList()
+				asList(2, 3), wrap(null, 2, 3).flatNonNull(Collections::singletonList).toList()
 		);
 	}
 
@@ -560,14 +560,14 @@ public class AbstractEnhancedWrappedStreamTest {
 	@Test
 	public void testMap() {
 		Assert.assertEquals(
-			asList("1", "2", "3"), wrap(1, 2, 3).map(String::valueOf).toList()
+				asList("1", "2", "3"), wrap(1, 2, 3).map(String::valueOf).toList()
 		);
 	}
 
 	@Test
 	public void testMapNonNull() {
 		Assert.assertEquals(
-			asList("3"), wrap(null, 2, 3, 4).mapNonNull(t -> ((t & 1) == 0) ? null : String.valueOf(t)).toList()
+				asList("3"), wrap(null, 2, 3, 4).mapNonNull(t -> ((t & 1) == 0) ? null : String.valueOf(t)).toList()
 		);
 	}
 
@@ -575,10 +575,10 @@ public class AbstractEnhancedWrappedStreamTest {
 	public void testMapIdx() {
 		final List indexes = new ArrayList<>();
 		Assert.assertEquals(
-			asList("1", "2", "3"), wrap(1, 2, 3).mapIdx((t, i) -> {
-				indexes.add(i);
-				return String.valueOf(t);
-			}).toList()
+				asList("1", "2", "3"), wrap(1, 2, 3).mapIdx((t, i) -> {
+					indexes.add(i);
+					return String.valueOf(t);
+				}).toList()
 		);
 		Assert.assertEquals(asList(0, 1, 2), indexes);
 	}
@@ -586,10 +586,10 @@ public class AbstractEnhancedWrappedStreamTest {
 	@Test
 	public void testMapMulti() {
 		Assert.assertEquals(
-			asList(1, 2, 3),
-			wrap(1, 2, 3).mapMulti((t, builder) -> {
-				builder.accept(t);
-			}).toList()
+				asList(1, 2, 3),
+				wrap(1, 2, 3).mapMulti((t, builder) -> {
+					builder.accept(t);
+				}).toList()
 		);
 	}
 
@@ -613,19 +613,19 @@ public class AbstractEnhancedWrappedStreamTest {
 
 	@Test
 	public void testToEntries() {
-		final Map expect = new HashMap(){{
+		final Map expect = new HashMap() {{
 			put(1, 1);
 			put(2, 2);
 			put(3, 3);
 		}};
 		Map map = EasyStream.of(1, 2, 3)
-			.toEntries(Function.identity(), Function.identity())
-			.toMap();
+				.toEntries(Function.identity(), Function.identity())
+				.toMap();
 		Assert.assertEquals(expect, map);
 
 		map = EasyStream.of(1, 2, 3)
-			.toEntries(Function.identity())
-			.toMap();
+				.toEntries(Function.identity())
+				.toMap();
 		Assert.assertEquals(expect, map);
 	}
 
@@ -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)).zip(list, (e1, e2) -> e1 + "." + e2).toList();
+		zip = 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);
 	}
 

From fc532551af8f8a338348c6a66779f9f7e897da7a Mon Sep 17 00:00:00 2001
From: VampireAchao 
Date: Fri, 9 Sep 2022 14:41:10 +0800
Subject: [PATCH 2/4] =?UTF-8?q?:trollface:=20=E5=A2=9E=E5=BC=BAEasyStream#?=
 =?UTF-8?q?zip=E5=AF=B9=E5=B9=B6=E8=A1=8C=E6=B5=81=E7=9A=84=E6=94=AF?=
 =?UTF-8?q?=E6=8C=81=EF=BC=8C=E6=8F=90=E4=BE=9BCollectorUtil.entryToMap?=
 =?UTF-8?q?=E5=AF=B9Entry=E8=BD=ACmap=E6=8F=90=E4=BE=9B=E6=94=AF=E6=8C=81?=
 =?UTF-8?q?=EF=BC=8C=E5=AE=8C=E5=96=84javadoc?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../stream/TransformableWrappedStream.java    | 44 +++++++------------
 1 file changed, 17 insertions(+), 27 deletions(-)

diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/TransformableWrappedStream.java b/hutool-core/src/main/java/cn/hutool/core/stream/TransformableWrappedStream.java
index d621278da..ad7b314cc 100644
--- a/hutool-core/src/main/java/cn/hutool/core/stream/TransformableWrappedStream.java
+++ b/hutool-core/src/main/java/cn/hutool/core/stream/TransformableWrappedStream.java
@@ -3,7 +3,6 @@ package cn.hutool.core.stream;
 import cn.hutool.core.collection.ListUtil;
 import cn.hutool.core.collection.iter.IterUtil;
 import cn.hutool.core.lang.Console;
-import cn.hutool.core.lang.Opt;
 import cn.hutool.core.lang.mutable.MutableInt;
 import cn.hutool.core.lang.mutable.MutableObj;
 import cn.hutool.core.map.MapUtil;
@@ -40,24 +39,15 @@ public interface TransformableWrappedStream EasyStream zip(
-		final Iterable other,
-		final BiFunction zipper) {
+			final Iterable other,
+			final BiFunction zipper) {
 		Objects.requireNonNull(zipper);
-		final Spliterator keys = spliterator();
-		final Spliterator values = Opt.ofNullable(other).map(Iterable::spliterator).orElseGet(Spliterators::emptySpliterator);
-		// 获取两个Spliterator的中较小的数量
-		// 如果Spliterator经过流操作, getExactSizeIfKnown()可能会返回-1, 所以默认大小为 ArrayList.DEFAULT_CAPACITY
-		final int sizeIfKnown = (int) Math.max(Math.min(keys.getExactSizeIfKnown(), values.getExactSizeIfKnown()), 10);
-		final List list = new ArrayList<>(sizeIfKnown);
-		// 保存第一个Spliterator的值
-		final MutableObj key = new MutableObj<>();
-		// 保存第二个Spliterator的值
-		final MutableObj value = new MutableObj<>();
-		// 当两个Spliterator中都还有剩余元素时
-		while (keys.tryAdvance(key::set) && values.tryAdvance(value::set)) {
-			list.add(zipper.apply(key.get(), value.get()));
+		Map idxIdentityMap = mapIdx((e, idx) -> MapUtil.entry(idx, e)).collect(CollectorUtil.entryToMap());
+		Map idxOtherMap = EasyStream.of(other).mapIdx((e, idx) -> MapUtil.entry(idx, e)).collect(CollectorUtil.entryToMap());
+		if (idxIdentityMap.size() <= idxOtherMap.size()) {
+			return EasyStream.of(idxIdentityMap.keySet(), isParallel()).map(k -> zipper.apply(idxIdentityMap.get(k), idxOtherMap.get(k)));
 		}
-		return EasyStream.of(list).parallel(isParallel()).onClose(unwrap()::close);
+		return EasyStream.of(idxOtherMap.keySet(), isParallel()).map(k -> zipper.apply(idxIdentityMap.get(k), idxOtherMap.get(k)));
 	}
 
 	/**
@@ -78,9 +68,9 @@ public interface TransformableWrappedStream>of(EasyStream.of(list, isParallel()));
 		}
 		return EasyStream.iterate(0, i -> i < size, i -> i + batchSize)
-			.map(skip -> EasyStream.of(list.subList(skip, Math.min(size, skip + batchSize)), isParallel()))
-			.parallel(isParallel())
-			.onClose(unwrap()::close);
+				.map(skip -> EasyStream.of(list.subList(skip, Math.min(size, skip + batchSize)), isParallel()))
+				.parallel(isParallel())
+				.onClose(unwrap()::close);
 	}
 
 	/**
@@ -114,8 +104,8 @@ public interface TransformableWrappedStream         键类型
+	 * @param keyMapper 键的映射方法
+	 * @param        键类型
 	 * @return {@link EntryStream}实例
 	 */
 	default  EntryStream toEntries(final Function keyMapper) {
@@ -159,7 +149,7 @@ public interface TransformableWrappedStream elements = unwrap().collect(Collectors.toList());
 		return wrap(ListUtil.splice(elements, start, deleteCount, items).stream())
-			.parallel(isParallel());
+				.parallel(isParallel());
 	}
 
 	/**
@@ -262,6 +252,7 @@ public interface TransformableWrappedStream>> recursiveRef = new MutableObj<>();
-		@SuppressWarnings("unchecked")
-		final Function> recursive = e -> EasyStream.of(childrenGetter.apply(e))
-			.flat(recursiveRef.get())
-			.unshift(e);
+		@SuppressWarnings("unchecked") final Function> recursive = e -> EasyStream.of(childrenGetter.apply(e))
+				.flat(recursiveRef.get())
+				.unshift(e);
 		recursiveRef.set(recursive);
 		return wrap(flatMap(recursive).peek(e -> childrenSetter.accept(e, null)));
 	}

From d1b125c88fe072328ff7a87b3167ca5753cefe5e Mon Sep 17 00:00:00 2001
From: VampireAchao 
Date: Fri, 9 Sep 2022 14:43:26 +0800
Subject: [PATCH 3/4] =?UTF-8?q?:trollface:=20=E6=B7=BB=E5=8A=A0author?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../java/cn/hutool/core/stream/TransformableWrappedStream.java  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/TransformableWrappedStream.java b/hutool-core/src/main/java/cn/hutool/core/stream/TransformableWrappedStream.java
index ad7b314cc..b90b911d4 100644
--- a/hutool-core/src/main/java/cn/hutool/core/stream/TransformableWrappedStream.java
+++ b/hutool-core/src/main/java/cn/hutool/core/stream/TransformableWrappedStream.java
@@ -23,7 +23,7 @@ import java.util.stream.StreamSupport;
  *
  * @param  流中的元素类型
  * @param  {@link TransformableWrappedStream}的实现类类型
- * @author huangchengxing
+ * @author huangchengxing VampireAchao
  * @since 6.0.0
  */
 public interface TransformableWrappedStream> extends WrappedStream {

From e09656b6cd051b3b576562ed388414456b4c92d2 Mon Sep 17 00:00:00 2001
From: VampireAchao 
Date: Fri, 9 Sep 2022 14:44:49 +0800
Subject: [PATCH 4/4] =?UTF-8?q?:trollface:=20=E6=B7=BB=E5=8A=A0author?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../cn/hutool/core/stream/AbstractEnhancedWrappedStream.java    | 2 +-
 .../java/cn/hutool/core/stream/TerminableWrappedStream.java     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/AbstractEnhancedWrappedStream.java b/hutool-core/src/main/java/cn/hutool/core/stream/AbstractEnhancedWrappedStream.java
index 25e4bc2b3..687d47ea8 100644
--- a/hutool-core/src/main/java/cn/hutool/core/stream/AbstractEnhancedWrappedStream.java
+++ b/hutool-core/src/main/java/cn/hutool/core/stream/AbstractEnhancedWrappedStream.java
@@ -8,7 +8,7 @@ import java.util.stream.Stream;
  *
  * @param  流中的元素类型
  * @param  {@link AbstractEnhancedWrappedStream}的实现类类型
- * @author huangchengxing
+ * @author huangchengxing VampireAchao
  * @see EasyStream
  * @see EntryStream
  * @since 6.0.0
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 17344f511..e329f9901 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
@@ -17,7 +17,7 @@ import java.util.stream.Stream;
  *
  * @param  流中的元素类型
  * @param  {@link TerminableWrappedStream}的实现类类型
- * @author huangchengxing
+ * @author huangchengxing VampireAchao
  * @since 6.0.0
  */
 public interface TerminableWrappedStream> extends WrappedStream {