limit(Predicate super T> predicate) {
+ return takeWhile(predicate);
+ }
+
+ /**
+ * 删除 与指定断言 匹配的元素, 在第一次不匹配时终止, 返回当前(第一个不匹配元素)及剩余元素组成的新流
+ * 与 jdk9 中的 dropWhile 方法不太一样, 这里的实现是个 顺序的、有状态的中间操作
+ * 本环节中是顺序执行的, 但是后续操作可以支持并行流: {@code
+ * FastStream.iterate(1, i <= 100, i -> i + 1)
+ * .parallel()
+ * // 顺序执行
+ * .dropWhile(e -> e < 50)
+ * // 并发
+ * .map(e -> e + 1)
+ * // 并发
+ * .map(String::valueOf)
+ * .toList();
+ * }
+ * 但是不建议在并行流中使用, 除非你确定 dropWhile 之后的操作能在并行流中受益很多
+ *
+ * @param predicate 断言
+ * @return 剩余元素组成的流
+ */
+ public FastStream dropWhile(Predicate super T> predicate) {
+ Objects.requireNonNull(predicate);
+ return of(StreamHelper.dropWhile(stream, predicate));
+ }
+
+ /**
+ * 跳过 与断言匹配的元素, 在第一次不匹配时终止, 返回当前(第一个不匹配元素)及剩余元素组成的新流
+ * dropWhile 的别名方法
+ *
+ * @param predicate 断言
+ * @return 剩余元素组成的流
+ * @see #dropWhile(Predicate)
+ */
+ public FastStream skip(Predicate super T> predicate) {
+ return dropWhile(predicate);
+ }
+
public interface FastStreamBuilder extends Consumer, cn.hutool.core.builder.Builder> {
/**
diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/support/DropWhileSpliterator.java b/hutool-core/src/main/java/cn/hutool/core/stream/support/DropWhileSpliterator.java
new file mode 100644
index 000000000..0ab4433a9
--- /dev/null
+++ b/hutool-core/src/main/java/cn/hutool/core/stream/support/DropWhileSpliterator.java
@@ -0,0 +1,72 @@
+package cn.hutool.core.stream.support;
+
+import java.util.Comparator;
+import java.util.Spliterator;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+
+/**
+ * dropWhile 的 Spliterator
+ * 借鉴自StreamEx
+ *
+ * @author emptypoint
+ * @since 6.0.0
+ */
+class DropWhileSpliterator implements Spliterator {
+
+ static DropWhileSpliterator create(Spliterator source, Predicate super T> predicate) {
+ return new DropWhileSpliterator<>(source, predicate);
+ }
+
+ private final Spliterator source;
+ private final Predicate super T> predicate;
+ private boolean isFound = false;
+
+ private DropWhileSpliterator(Spliterator source, Predicate super T> predicate) {
+ this.source = source;
+ this.predicate = predicate;
+ }
+
+ @Override
+ public boolean tryAdvance(Consumer super T> action) {
+ boolean hasNext = true;
+ // 如果 还没找到 并且 流中还有元素 继续找
+ while (!isFound && hasNext) {
+ hasNext = source.tryAdvance(e -> {
+ if (!predicate.test(e)) {
+ // 第一次不匹配
+ isFound = true;
+ action.accept(e);
+ }
+ });
+ }
+
+ // 对找到的元素进行后续处理
+ if (isFound) {
+ source.forEachRemaining(action);
+ }
+
+ // 该环节已经处理完成
+ return false;
+ }
+
+ @Override
+ public Spliterator trySplit() {
+ return null;
+ }
+
+ @Override
+ public long estimateSize() {
+ return Long.MAX_VALUE;
+ }
+
+ @Override
+ public int characteristics() {
+ return source.characteristics() & ~Spliterator.SIZED;
+ }
+
+ @Override
+ public Comparator super T> getComparator() {
+ return source.getComparator();
+ }
+}
diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/support/IterateSpliterator.java b/hutool-core/src/main/java/cn/hutool/core/stream/support/IterateSpliterator.java
new file mode 100644
index 000000000..71df09b7b
--- /dev/null
+++ b/hutool-core/src/main/java/cn/hutool/core/stream/support/IterateSpliterator.java
@@ -0,0 +1,76 @@
+package cn.hutool.core.stream.support;
+
+import java.util.Objects;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.function.UnaryOperator;
+
+/**
+ * 无限有序流 的Spliterator
+ *
+ * @author VampireAchao
+ * @since 6.0.0
+ */
+class IterateSpliterator extends Spliterators.AbstractSpliterator {
+ public static IterateSpliterator create(T seed, Predicate super T> hasNext, UnaryOperator next) {
+ return new IterateSpliterator<>(seed, hasNext, next);
+ }
+
+ /**
+ * Creates a spliterator reporting the given estimated size and
+ * additionalCharacteristics.
+ */
+ IterateSpliterator(T seed, Predicate super T> hasNext, UnaryOperator next) {
+ super(Long.MAX_VALUE, Spliterator.ORDERED | Spliterator.IMMUTABLE);
+ this.seed = seed;
+ this.hasNext = hasNext;
+ this.next = next;
+ }
+
+ private final T seed;
+ private final Predicate super T> hasNext;
+ private final UnaryOperator next;
+ private T prev;
+ private boolean started;
+ private boolean finished;
+
+ @Override
+ public boolean tryAdvance(Consumer super T> action) {
+ Objects.requireNonNull(action);
+ if (finished) {
+ return false;
+ }
+ T t;
+ if (started) {
+ t = next.apply(prev);
+ } else {
+ t = seed;
+ started = true;
+ }
+ if (!hasNext.test(t)) {
+ prev = null;
+ finished = true;
+ return false;
+ }
+ prev = t;
+ action.accept(prev);
+ return true;
+ }
+
+ @Override
+ public void forEachRemaining(Consumer super T> action) {
+ Objects.requireNonNull(action);
+ if (finished) {
+ return;
+ }
+ finished = true;
+ T t = started ? next.apply(prev) : seed;
+ prev = null;
+ while (hasNext.test(t)) {
+ action.accept(t);
+ t = next.apply(t);
+ }
+ }
+}
diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/support/StreamHelper.java b/hutool-core/src/main/java/cn/hutool/core/stream/support/StreamHelper.java
new file mode 100644
index 000000000..478cbb091
--- /dev/null
+++ b/hutool-core/src/main/java/cn/hutool/core/stream/support/StreamHelper.java
@@ -0,0 +1,99 @@
+package cn.hutool.core.stream.support;
+
+import java.util.Spliterator;
+import java.util.function.Predicate;
+import java.util.function.UnaryOperator;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * FastStream 辅助工具类
+ *
+ * @author emptypoint
+ * @since 6.0.0
+ */
+public final class StreamHelper {
+ private StreamHelper() {
+ }
+
+ /**
+ * 返回无限有序流
+ * 该流由 初始值 然后判断条件 以及执行 迭代函数 进行迭代获取到元素
+ *
+ * @param 元素类型
+ * @param seed 初始值
+ * @param hasNext 条件值
+ * @param next 用上一个元素作为参数执行并返回一个新的元素
+ * @return 无限有序流
+ */
+ public static Stream iterate(T seed, Predicate super T> hasNext, UnaryOperator next) {
+ requireNonNull(next);
+ requireNonNull(hasNext);
+ return StreamSupport.stream(IterateSpliterator.create(seed, hasNext, next), false);
+ }
+
+ /**
+ * 保留 与指定断言 匹配时的元素, 在第一次不匹配时终止, 抛弃当前(第一个不匹配元素)及后续所有元素
+ * 与 jdk9 中的 takeWhile 方法不太一样, 这里的实现是个 顺序的、有状态的中间操作
+ * 本环节中是顺序执行的, 但是后续操作可以支持并行流
+ * 但是不建议在并行流中使用, 除非你确定 takeWhile 之后的操作能在并行流中受益很多
+ *
+ * @param source 源流
+ * @param 元素类型
+ * @param predicate 断言
+ * @return 与指定断言匹配的元素组成的流
+ */
+ public static Stream takeWhile(Stream source, Predicate super T> predicate) {
+ requireNonNull(source);
+ requireNonNull(predicate);
+ return createStatefulNewStream(source, TakeWhileSpliterator.create(source.spliterator(), predicate));
+ }
+
+ /**
+ * 删除 与指定断言 匹配的元素, 在第一次不匹配时终止, 返回当前(第一个不匹配元素)及剩余元素组成的新流
+ * 与 jdk9 中的 dropWhile 方法不太一样, 这里的实现是个 顺序的、有状态的中间操作
+ * 本环节中是顺序执行的, 但是后续操作可以支持并行流
+ * 但是不建议在并行流中使用, 除非你确定 dropWhile 之后的操作能在并行流中受益很多
+ *
+ * @param source 源流
+ * @param 元素类型
+ * @param predicate 断言
+ * @return 剩余元素组成的流
+ */
+ public static Stream dropWhile(Stream source, Predicate super T> predicate) {
+ requireNonNull(source);
+ requireNonNull(predicate);
+ return createStatefulNewStream(source, DropWhileSpliterator.create(source.spliterator(), predicate));
+ }
+
+ // region 私有方法
+ /* ================================================== 私有方法 =================================================== */
+
+ /**
+ * 根据 源流 和 新的Spliterator 生成新的流
+ * 这是一个 顺序的、有状态的流
+ * 在新流的第一个节点是顺序执行的, 但是后续操作可以支持并行流
+ *
+ * @param source 源流
+ * @param newSpliterator 新流的Spliterator
+ * @param 旧流的元素类型
+ * @param 新流的元素类型
+ * @return 新流
+ */
+ private static Stream createStatefulNewStream(Stream source, Spliterator newSpliterator) {
+ // 创建新流
+ Stream newStream = StreamSupport.stream(newSpliterator, source.isParallel());
+ // 如果旧流是并行流, 新流主动调用一个有状态的操作, 虽然没有意义, 但是可以让后续的无状态节点正常并发
+ if (source.isParallel()) {
+ newStream = newStream.limit(Long.MAX_VALUE);
+ }
+ // 由于新流不与旧流的节点关联, 所以需要主动设置旧流的close方法, 哪怕几乎不可能有人在旧流上设置onClose操作
+ return newStream.onClose(source::close);
+ }
+
+ /* ============================================================================================================== */
+ // endregion
+
+}
diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/support/TakeWhileSpliterator.java b/hutool-core/src/main/java/cn/hutool/core/stream/support/TakeWhileSpliterator.java
new file mode 100644
index 000000000..dc0ca8da6
--- /dev/null
+++ b/hutool-core/src/main/java/cn/hutool/core/stream/support/TakeWhileSpliterator.java
@@ -0,0 +1,68 @@
+package cn.hutool.core.stream.support;
+
+import java.util.Comparator;
+import java.util.Spliterator;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+
+/**
+ * takeWhile 的 Spliterator
+ * 借鉴自StreamEx
+ *
+ * @author emptypoint
+ * @since 6.0.0
+ */
+class TakeWhileSpliterator implements Spliterator {
+
+ static TakeWhileSpliterator create(Spliterator source, Predicate super T> predicate) {
+ return new TakeWhileSpliterator<>(source, predicate);
+ }
+
+ private final Spliterator source;
+ private final Predicate super T> predicate;
+ private boolean isContinue = true;
+
+ TakeWhileSpliterator(Spliterator source, Predicate super T> predicate) {
+ this.source = source;
+ this.predicate = predicate;
+ }
+
+ @Override
+ public boolean tryAdvance(Consumer super T> action) {
+ boolean hasNext = true;
+ // 如果 还可以继续 并且 流中还有元素 则继续遍历
+ while (isContinue && hasNext) {
+ hasNext = source.tryAdvance(e -> {
+ if (predicate.test(e)) {
+ action.accept(e);
+ } else {
+ // 终止遍历剩下的元素
+ isContinue = false;
+ }
+ });
+ }
+ // 该环节已经处理完成
+ return false;
+ }
+
+ @Override
+ public Spliterator trySplit() {
+ return null;
+ }
+
+ @Override
+ public long estimateSize() {
+ return isContinue ? source.estimateSize() : 0;
+ }
+
+ @Override
+ public int characteristics() {
+ return source.characteristics() & ~(Spliterator.SIZED | Spliterator.SUBSIZED);
+ }
+
+ @Override
+ public Comparator super T> getComparator() {
+ return source.getComparator();
+ }
+}
+
diff --git a/hutool-core/src/test/java/cn/hutool/core/stream/FastStreamTest.java b/hutool-core/src/test/java/cn/hutool/core/stream/FastStreamTest.java
index 9091ec6a0..937b7378d 100644
--- a/hutool-core/src/test/java/cn/hutool/core/stream/FastStreamTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/stream/FastStreamTest.java
@@ -76,7 +76,7 @@ public class FastStreamTest {
Map toZip = FastStream.of(orders).toZip(list);
Assert.assertEquals(map, toZip);
- Map toZipParallel = FastStream.of(orders).parallel().toZip(list);
+ Map toZipParallel = FastStream.of(orders).parallel().nonNull().toZip(list);
Assert.assertEquals(map, toZipParallel);
}
@@ -241,10 +241,12 @@ public class FastStreamTest {
@Test
public void testAt() {
List list = Arrays.asList(1, 2, 3);
- Assert.assertEquals(1, (Object) FastStream.of(list).at(0));
- Assert.assertEquals(1, (Object) FastStream.of(list).at(-3));
- Assert.assertEquals(3, (Object) FastStream.of(list).at(-1));
- Assert.assertNull(FastStream.of(list).at(-4));
+ Assert.assertEquals(1, (Object) FastStream.of(list).at(0).orElse(null));
+ Assert.assertEquals(2, (Object) FastStream.of(list).at(1).orElse(null));
+ Assert.assertEquals(3, (Object) FastStream.of(list).at(2).orElse(null));
+ Assert.assertEquals(1, (Object) FastStream.of(list).at(-3).orElse(null));
+ Assert.assertEquals(3, (Object) FastStream.of(list).at(-1).orElse(null));
+ Assert.assertNull(FastStream.of(list).at(-4).orElse(null));
}
@Test
@@ -262,34 +264,46 @@ public class FastStreamTest {
@Test
public void testFindFirst() {
List list = Arrays.asList(1, 2, 3);
- Integer find = FastStream.of(list).findFirst(Objects::nonNull);
+ Integer find = FastStream.of(list).findFirst(Objects::nonNull).orElse(null);
Assert.assertEquals(1, (Object) find);
}
@Test
public void testFindFirstIdx() {
List list = Arrays.asList(null, 2, 3);
- Integer idx = FastStream.of(list).findFirstIdx(Objects::nonNull);
- Assert.assertEquals(1, (Object) idx);
+ Assert.assertEquals(1, FastStream.of(list).findFirstIdx(Objects::nonNull));
Assert.assertEquals(-1, (Object) FastStream.of(list).parallel().findFirstIdx(Objects::nonNull));
}
@Test
public void testFindLast() {
- List list = ListUtil.of(1, null, 3);
- Integer find = FastStream.of(list).parallel().findLast(Objects::nonNull);
- Assert.assertEquals(3, (Object) find);
+ List list = ListUtil.of(1, 2, 4, 5, 6, 7, 8, 9, 10, 3);
+ Assert.assertEquals(3, (Object) FastStream.of(list).findLast().orElse(null));
Assert.assertEquals(3, (Object) FastStream.of(list).parallel().findLast().orElse(null));
+
+ List list2 = ListUtil.of(1, 2, 4, 5, 6, 7, 8, 9, 10, 3, null);
+ Assert.assertEquals(3, (Object) FastStream.of(list2).parallel().findLast(Objects::nonNull).orElse(null));
+
+ Assert.assertNull(FastStream.of().parallel().findLast(Objects::nonNull).orElse(null));
+ Assert.assertNull(FastStream.of((Object) null).parallel().findLast(Objects::nonNull).orElse(null));
}
@Test
public void testFindLastIdx() {
List list = Arrays.asList(1, null, 3);
- Integer idx = FastStream.of(list).findLastIdx(Objects::nonNull);
- Assert.assertEquals(2, (Object) idx);
+ Assert.assertEquals(2, (Object) FastStream.of(list).findLastIdx(Objects::nonNull));
Assert.assertEquals(-1, (Object) FastStream.of(list).parallel().findLastIdx(Objects::nonNull));
}
+ @Test
+ public void testReverse() {
+ final List list = ListUtil.of(Stream.iterate(1, i -> i + 1).limit(1000).collect(Collectors.toList()));
+
+ Assert.assertEquals(ListUtil.reverseNew(list), FastStream.of(list).reverse().toList());
+ Assert.assertEquals(ListUtil.empty(), FastStream.of().reverse().toList());
+ Assert.assertEquals(ListUtil.of((Object) null), FastStream.of((Object) null).reverse().toList());
+ }
+
@Test
public void testZip() {
List orders = Arrays.asList(1, 2, 3);
@@ -319,4 +333,59 @@ public class FastStreamTest {
lists = FastStream.of(list).splitList(list.size()).toList();
Assert.assertEquals(singletonList(list), lists);
}
+
+ @Test
+ public void testTakeWhile() {
+ // 1 到 10
+ final List list = FastStream.iterate(1, i -> i <= 10, i -> i + 1).toList();
+
+ final List res1 = FastStream.of(list)
+ // 舍弃 5
+ .takeWhile(e -> e < 5)
+ // 过滤奇数
+ .filter(e -> (e & 1) == 0)
+ // 反序
+ .sorted(Comparator.reverseOrder())
+ .map(String::valueOf)
+ .toList();
+ Assert.assertEquals(Arrays.asList("4", "2"), res1);
+
+ final List res2 = FastStream.iterate(1, i -> i + 1)
+ .parallel()
+ .takeWhile(e -> e < 5)
+ .map(String::valueOf)
+ .map(Integer::valueOf)
+ .sorted(Comparator.naturalOrder())
+ .toList();
+ Assert.assertEquals(Arrays.asList(1, 2, 3, 4), res2);
+ }
+
+ @Test
+ public void testDropWhile() {
+ // 1 到 10
+ final List list = FastStream.iterate(1, i -> i <= 10, i -> i + 1).toList();
+
+ final List res1 = FastStream.of(list)
+ // 舍弃 5之前的数字
+ .dropWhile(e -> e < 5)
+ // 过滤偶数
+ .filter(e -> (e & 1) == 1)
+ // 反序
+ .sorted(Comparator.reverseOrder())
+ .map(String::valueOf)
+ .toList();
+ Assert.assertEquals(Arrays.asList("9", "7", "5"), res1);
+
+ final List res2 = FastStream.of(list)
+ .parallel()
+ .dropWhile(e -> e < 5)
+ // 过滤偶数
+ .filter(e -> (e & 1) == 1)
+ .map(String::valueOf)
+ .map(Integer::valueOf)
+ .sorted(Comparator.naturalOrder())
+ .toList();
+ Assert.assertEquals(Arrays.asList(5, 7, 9), res2);
+ }
+
}
From 3608f9dbe025103b795b5c6b2532688f154eef20 Mon Sep 17 00:00:00 2001
From: Zjp <1215582715@qq.com>
Date: Fri, 5 Aug 2022 17:06:21 +0800
Subject: [PATCH 2/7] =?UTF-8?q?fixed=20fc8923b=20from=20https://gitee.com/?=
=?UTF-8?q?VampireAchao/hutool/pulls/742=20=E4=BC=98=E5=8C=96FastStream:?=
=?UTF-8?q?=201.=E6=96=B0=E5=A2=9EtakeWhile=E3=80=81dropWhile=E6=96=B9?=
=?UTF-8?q?=E6=B3=95;=202.=E4=BC=98=E5=8C=96=E9=83=A8=E5=88=86=E5=86=99?=
=?UTF-8?q?=E6=B3=95,=20=E5=B8=8C=E6=9C=9B=E8=BF=9B=E4=B8=80=E6=AD=A5?=
=?UTF-8?q?=E6=8F=90=E9=AB=98=E6=95=88=E7=8E=87;=203.=E5=88=A0=E9=99=A4?=
=?UTF-8?q?=E5=A4=9A=E4=BD=99=E7=9A=84=E4=BB=A3=E7=A0=81,=20=E7=A7=BB?=
=?UTF-8?q?=E5=8A=A8=E9=83=A8=E5=88=86=E4=BB=A3=E7=A0=81=E5=88=B0=E5=85=B6?=
=?UTF-8?q?=E4=BB=96=E7=B1=BB=E4=B8=AD;?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../cn/hutool/core/collection/ListUtil.java | 48 +++
.../main/java/cn/hutool/core/lang/Opt.java | 13 +
.../hutool/core/lang/mutable/MutableInt.java | 41 +++
.../hutool/core/lang/mutable/MutableObj.java | 14 +-
.../cn/hutool/core/stream/FastStream.java | 297 +++++++++---------
.../stream/support/DropWhileSpliterator.java | 72 +++++
.../stream/support/IterateSpliterator.java | 76 +++++
.../core/stream/support/StreamHelper.java | 99 ++++++
.../stream/support/TakeWhileSpliterator.java | 68 ++++
.../cn/hutool/core/stream/FastStreamTest.java | 95 +++++-
10 files changed, 660 insertions(+), 163 deletions(-)
create mode 100644 hutool-core/src/main/java/cn/hutool/core/stream/support/DropWhileSpliterator.java
create mode 100644 hutool-core/src/main/java/cn/hutool/core/stream/support/IterateSpliterator.java
create mode 100644 hutool-core/src/main/java/cn/hutool/core/stream/support/StreamHelper.java
create mode 100644 hutool-core/src/main/java/cn/hutool/core/stream/support/TakeWhileSpliterator.java
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 28f446daa..e21f3aa92 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
@@ -13,6 +13,7 @@ import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.PageUtil;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
@@ -692,4 +693,51 @@ public class ListUtil {
}
return list;
}
+
+ /**
+ * 类似js的splice函数
+ *
+ * @param start 起始下标, 可以为负数, -1代表最后一个元素
+ * @param deleteCount 删除个数,必须是正整数
+ * @param items 放入值
+ * @return 操作后的流
+ * @since 6.0.0
+ */
+ @SafeVarargs
+ public static List splice(List list, int start, int deleteCount, T... items) {
+ if (CollUtil.isEmpty(list)) {
+ return zero();
+ }
+ final int size = list.size();
+ // 从后往前查找
+ if (start < 0) {
+ start += size;
+ } else if (start >= size) {
+ // 直接在尾部追加,不删除
+ start = size;
+ deleteCount = 0;
+ }
+ // 起始位置 加上 删除的数量 超过 数据长度,需要重新计算需要删除的数量
+ if (start + deleteCount > size) {
+ deleteCount = size - start;
+ }
+
+ // 新列表的长度
+ final int newSize = size - deleteCount + items.length;
+ List resList = list;
+ // 新列表的长度 大于 旧列表,创建新列表
+ if (newSize > size) {
+ resList = new ArrayList<>(newSize);
+ resList.addAll(list);
+ }
+ // 需要删除的部分
+ if (deleteCount > 0) {
+ resList.subList(start, start + deleteCount).clear();
+ }
+ // 新增的部分
+ if (ArrayUtil.isNotEmpty(items)) {
+ resList.addAll(start, Arrays.asList(items));
+ }
+ return resList;
+ }
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/Opt.java b/hutool-core/src/main/java/cn/hutool/core/lang/Opt.java
index e4730f1f3..66315b586 100644
--- a/hutool-core/src/main/java/cn/hutool/core/lang/Opt.java
+++ b/hutool-core/src/main/java/cn/hutool/core/lang/Opt.java
@@ -127,6 +127,19 @@ public class Opt {
}
}
+ /**
+ * 根据 {@link Optional} 构造 {@code Opt}
+ *
+ * @param optional optional
+ * @param 包裹的元素类型
+ * @return 一个包裹里元素可能为空的 {@code Opt}
+ * @since 6.0.0
+ */
+ @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
+ public static Opt of(Optional optional) {
+ return ofNullable(optional).flattedMap(Function.identity());
+ }
+
/**
* 包裹里实际的元素
*/
diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableInt.java b/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableInt.java
index 912a67afc..9cb300af5 100644
--- a/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableInt.java
+++ b/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableInt.java
@@ -81,6 +81,47 @@ public class MutableInt extends Number implements Comparable, Mutabl
return this;
}
+ // -----------------------------------------------------------------------
+ /**
+ * 先加1, 再获取值
+ *
+ * @return +1后的值
+ * @since 6.0.0
+ */
+ public int incrementAndGet() {
+ return ++value;
+ }
+
+ /**
+ * 先获取原来的值, 再加1
+ *
+ * @return 原始值
+ * @since 6.0.0
+ */
+ public int getAndIncrement() {
+ return value++;
+ }
+
+ /**
+ * 先减1, 再获取值
+ *
+ * @return -1后的值
+ * @since 6.0.0
+ */
+ public int decrementAndGet() {
+ return --value;
+ }
+
+ /**
+ * 先获取原来的值, 再减1
+ *
+ * @return 原始值
+ * @since 6.0.0
+ */
+ public int getAndDecrement() {
+ return value--;
+ }
+
// -----------------------------------------------------------------------
/**
* 增加值
diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableObj.java b/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableObj.java
index 64f71dc87..c8a9397b2 100644
--- a/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableObj.java
+++ b/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableObj.java
@@ -1,6 +1,7 @@
package cn.hutool.core.lang.mutable;
import java.io.Serializable;
+import java.util.function.Consumer;
/**
* 可变{@code Object}
@@ -8,7 +9,7 @@ import java.io.Serializable;
* @param 可变的类型
* @since 3.0.1
*/
-public class MutableObj implements Mutable, Serializable {
+public class MutableObj implements Mutable, Serializable, Consumer {
private static final long serialVersionUID = 1L;
/**
@@ -50,6 +51,17 @@ public class MutableObj implements Mutable, Serializable {
this.value = value;
}
+ /**
+ * 消费元素
+ *
+ * @param t t
+ * @since 6.0.0
+ */
+ @Override
+ public void accept(T t) {
+ this.value = t;
+ }
+
// -----------------------------------------------------------------------
@Override
public boolean equals(final Object obj) {
diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/FastStream.java b/hutool-core/src/main/java/cn/hutool/core/stream/FastStream.java
index 5c74135e0..350d6068c 100644
--- a/hutool-core/src/main/java/cn/hutool/core/stream/FastStream.java
+++ b/hutool-core/src/main/java/cn/hutool/core/stream/FastStream.java
@@ -1,12 +1,12 @@
package cn.hutool.core.stream;
-import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
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;
+import cn.hutool.core.stream.support.StreamHelper;
import cn.hutool.core.text.StrUtil;
import cn.hutool.core.util.ArrayUtil;
@@ -61,6 +61,7 @@ public class FastStream implements Stream, Iterable {
this.stream = stream;
}
+ // region Static method
// --------------------------------------------------------------- Static method start
/**
@@ -157,51 +158,7 @@ public class FastStream implements Stream, Iterable {
public static FastStream iterate(T seed, Predicate super T> hasNext, UnaryOperator next) {
Objects.requireNonNull(next);
Objects.requireNonNull(hasNext);
- Spliterator spliterator = new Spliterators.AbstractSpliterator(Long.MAX_VALUE,
- Spliterator.ORDERED | Spliterator.IMMUTABLE) {
- T prev;
- boolean started;
- boolean finished;
-
- @Override
- public boolean tryAdvance(Consumer super T> action) {
- Objects.requireNonNull(action);
- if (finished) {
- return false;
- }
- T t;
- if (started) {
- t = next.apply(prev);
- } else {
- t = seed;
- started = true;
- }
- if (!hasNext.test(t)) {
- prev = null;
- finished = true;
- return false;
- }
- prev = t;
- action.accept(prev);
- return true;
- }
-
- @Override
- public void forEachRemaining(Consumer super T> action) {
- Objects.requireNonNull(action);
- if (finished) {
- return;
- }
- finished = true;
- T t = started ? next.apply(prev) : seed;
- prev = null;
- while (hasNext.test(t)) {
- action.accept(t);
- t = next.apply(t);
- }
- }
- };
- return new FastStream<>(StreamSupport.stream(spliterator, false));
+ return new FastStream<>(StreamHelper.iterate(seed, hasNext, next));
}
/**
@@ -279,6 +236,7 @@ public class FastStream implements Stream, Iterable {
}
// --------------------------------------------------------------- Static method end
+ // endregion
/**
* 过滤元素,返回与指定断言匹配的元素组成的流
@@ -303,10 +261,9 @@ public class FastStream implements Stream, Iterable {
*/
public FastStream filter(Function super T, ? extends R> mapper, R value) {
Objects.requireNonNull(mapper);
- return filter(e -> Objects.equals(Opt.ofNullable(e).map(mapper).get(), value));
+ return filter(e -> Objects.equals(mapper.apply(e), value));
}
-
/**
* 过滤元素,返回与指定断言匹配的元素组成的流,断言带下标,并行流时下标永远为-1
* 这是一个无状态中间操作
@@ -320,7 +277,7 @@ public class FastStream implements Stream, Iterable {
return filter(e -> predicate.test(e, NOT_FOUND_INDEX));
} else {
MutableInt index = new MutableInt(NOT_FOUND_INDEX);
- return filter(e -> predicate.test(e, index.increment().get()));
+ return filter(e -> predicate.test(e, index.incrementAndGet()));
}
}
@@ -360,7 +317,7 @@ public class FastStream implements Stream, Iterable {
return map(e -> mapper.apply(e, NOT_FOUND_INDEX));
} else {
MutableInt index = new MutableInt(NOT_FOUND_INDEX);
- return map(e -> mapper.apply(e, index.increment().get()));
+ return map(e -> mapper.apply(e, index.incrementAndGet()));
}
}
@@ -395,7 +352,7 @@ public class FastStream implements Stream, Iterable {
return flatMap(e -> mapper.apply(e, NOT_FOUND_INDEX));
} else {
MutableInt index = new MutableInt(NOT_FOUND_INDEX);
- return flatMap(e -> mapper.apply(e, index.increment().get()));
+ return flatMap(e -> mapper.apply(e, index.incrementAndGet()));
}
}
@@ -449,7 +406,7 @@ public class FastStream implements Stream, Iterable {
*/
public