This commit is contained in:
Looly 2024-02-07 11:10:52 +08:00
parent d4b1d90548
commit 2b9eec0582
2 changed files with 51 additions and 45 deletions

View File

@ -12,9 +12,7 @@
package org.dromara.hutool.core.stream; package org.dromara.hutool.core.stream;
import static java.util.Objects.requireNonNull;
import org.dromara.hutool.core.io.IORuntimeException; import org.dromara.hutool.core.io.IORuntimeException;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.stream.spliterators.DropWhileSpliterator; import org.dromara.hutool.core.stream.spliterators.DropWhileSpliterator;
import org.dromara.hutool.core.stream.spliterators.IterateSpliterator; import org.dromara.hutool.core.stream.spliterators.IterateSpliterator;
import org.dromara.hutool.core.stream.spliterators.TakeWhileSpliterator; import org.dromara.hutool.core.stream.spliterators.TakeWhileSpliterator;
@ -26,10 +24,7 @@ import java.io.IOException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Collection; import java.util.*;
import java.util.Iterator;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.function.UnaryOperator; import java.util.function.UnaryOperator;
@ -47,12 +42,11 @@ public class StreamUtil {
/** /**
* @param array 数组 * @param array 数组
* @param <T> 元素类型 * @param <T> 元素类型
* @return {@link Stream} * @return {@link Stream}如果提供的array为{@code null}返回{@link Stream#empty()}
*/ */
@SafeVarargs @SafeVarargs
public static <T> Stream<T> of(final T... array) { public static <T> Stream<T> of(final T... array) {
Assert.notNull(array, "Array must be not null!"); return null == array ? Stream.empty() : Stream.of(array);
return Stream.of(array);
} }
/** /**
@ -60,7 +54,7 @@ public class StreamUtil {
* *
* @param iterable 集合 * @param iterable 集合
* @param <T> 集合元素类型 * @param <T> 集合元素类型
* @return {@link Stream} * @return {@link Stream}如果提供的iterator为{@code null}返回{@link Stream#empty()}
*/ */
public static <T> Stream<T> of(final Iterable<T> iterable) { public static <T> Stream<T> of(final Iterable<T> iterable) {
return of(iterable, false); return of(iterable, false);
@ -72,10 +66,12 @@ public class StreamUtil {
* @param iterable 集合 * @param iterable 集合
* @param parallel 是否并行 * @param parallel 是否并行
* @param <T> 集合元素类型 * @param <T> 集合元素类型
* @return {@link Stream} * @return {@link Stream}如果提供的iterator为{@code null}返回{@link Stream#empty()}
*/ */
public static <T> Stream<T> of(final Iterable<T> iterable, final boolean parallel) { public static <T> Stream<T> of(final Iterable<T> iterable, final boolean parallel) {
Assert.notNull(iterable, "Iterable must be not null!"); if (null == iterable) {
return Stream.empty();
}
return iterable instanceof Collection ? return iterable instanceof Collection ?
parallel ? ((Collection<T>) iterable).parallelStream() : ((Collection<T>) iterable).stream() : parallel ? ((Collection<T>) iterable).parallelStream() : ((Collection<T>) iterable).stream() :
StreamSupport.stream(iterable.spliterator(), parallel); StreamSupport.stream(iterable.spliterator(), parallel);
@ -86,8 +82,7 @@ public class StreamUtil {
* *
* @param iterator 迭代器 * @param iterator 迭代器
* @param <T> 集合元素类型 * @param <T> 集合元素类型
* @return {@link Stream} * @return {@link Stream}如果提供的iterator为{@code null}返回{@link Stream#empty()}
* @throws IllegalArgumentException 如果iterator为null抛出该异常
*/ */
public static <T> Stream<T> ofIter(final Iterator<T> iterator) { public static <T> Stream<T> ofIter(final Iterator<T> iterator) {
return ofIter(iterator, false); return ofIter(iterator, false);
@ -99,11 +94,12 @@ public class StreamUtil {
* @param iterator 迭代器 * @param iterator 迭代器
* @param parallel 是否并行 * @param parallel 是否并行
* @param <T> 集合元素类型 * @param <T> 集合元素类型
* @return {@link Stream} * @return {@link Stream}如果提供的iterator为{@code null}返回{@link Stream#empty()}
* @throws IllegalArgumentException 如果iterator为null抛出该异常
*/ */
public static <T> Stream<T> ofIter(final Iterator<T> iterator, final boolean parallel) { public static <T> Stream<T> ofIter(final Iterator<T> iterator, final boolean parallel) {
Assert.notNull(iterator, "iterator must not be null!"); if (null == iterator) {
return Stream.empty();
}
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), parallel); return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), parallel);
} }
@ -111,7 +107,7 @@ public class StreamUtil {
* 按行读取文件为{@link Stream} * 按行读取文件为{@link Stream}
* *
* @param file 文件 * @param file 文件
* @return {@link Stream} * @return {@link Stream}如果提供的file为{@code null}返回{@link Stream#empty()}
*/ */
public static Stream<String> of(final File file) { public static Stream<String> of(final File file) {
return of(file, CharsetUtil.UTF_8); return of(file, CharsetUtil.UTF_8);
@ -121,7 +117,7 @@ public class StreamUtil {
* 按行读取文件为{@link Stream} * 按行读取文件为{@link Stream}
* *
* @param path 路径 * @param path 路径
* @return {@link Stream} * @return {@link Stream}如果提供的file为{@code null}返回{@link Stream#empty()}
*/ */
public static Stream<String> of(final Path path) { public static Stream<String> of(final Path path) {
return of(path, CharsetUtil.UTF_8); return of(path, CharsetUtil.UTF_8);
@ -132,10 +128,12 @@ public class StreamUtil {
* *
* @param file 文件 * @param file 文件
* @param charset 编码 * @param charset 编码
* @return {@link Stream} * @return {@link Stream}如果提供的file为{@code null}返回{@link Stream#empty()}
*/ */
public static Stream<String> of(final File file, final Charset charset) { public static Stream<String> of(final File file, final Charset charset) {
Assert.notNull(file, "File must be not null!"); if (null == file) {
return Stream.empty();
}
return of(file.toPath(), charset); return of(file.toPath(), charset);
} }
@ -144,9 +142,12 @@ public class StreamUtil {
* *
* @param path 路径 * @param path 路径
* @param charset 编码 * @param charset 编码
* @return {@link Stream} * @return {@link Stream}如果提供的path为{@code null}返回{@link Stream#empty()}
*/ */
public static Stream<String> of(final Path path, final Charset charset) { public static Stream<String> of(final Path path, final Charset charset) {
if (null == path) {
return Stream.empty();
}
try { try {
return Files.lines(path, charset); return Files.lines(path, charset);
} catch (final IOException e) { } catch (final IOException e) {
@ -173,9 +174,12 @@ public class StreamUtil {
* @param stream {@link Stream} * @param stream {@link Stream}
* @param delimiter 分隔符 * @param delimiter 分隔符
* @param <T> 元素类型 * @param <T> 元素类型
* @return 字符串 * @return 字符串如果stream为{@code null}返回{@code null}
*/ */
public static <T> String join(final Stream<T> stream, final CharSequence delimiter) { public static <T> String join(final Stream<T> stream, final CharSequence delimiter) {
if (null == stream) {
return null;
}
return stream.collect(CollectorUtil.joining(delimiter)); return stream.collect(CollectorUtil.joining(delimiter));
} }
@ -186,10 +190,13 @@ public class StreamUtil {
* @param delimiter 分隔符 * @param delimiter 分隔符
* @param toStringFunc 元素转换为字符串的函数 * @param toStringFunc 元素转换为字符串的函数
* @param <T> 元素类型 * @param <T> 元素类型
* @return 字符串 * @return 字符串如果stream为{@code null}返回{@code null}
*/ */
public static <T> String join(final Stream<T> stream, final CharSequence delimiter, public static <T> String join(final Stream<T> stream, final CharSequence delimiter,
final Function<T, ? extends CharSequence> toStringFunc) { final Function<T, ? extends CharSequence> toStringFunc) {
if (null == stream) {
return null;
}
return stream.collect(CollectorUtil.joining(delimiter, toStringFunc)); return stream.collect(CollectorUtil.joining(delimiter, toStringFunc));
} }
@ -205,8 +212,8 @@ public class StreamUtil {
* @return 无限有序流 * @return 无限有序流
*/ */
public static <T> Stream<T> iterate(final T seed, final Predicate<? super T> hasNext, final UnaryOperator<T> next) { public static <T> Stream<T> iterate(final T seed, final Predicate<? super T> hasNext, final UnaryOperator<T> next) {
requireNonNull(next); Objects.requireNonNull(next);
requireNonNull(hasNext); Objects.requireNonNull(hasNext);
return StreamSupport.stream(IterateSpliterator.create(seed, hasNext, next), false); return StreamSupport.stream(IterateSpliterator.create(seed, hasNext, next), false);
} }
@ -228,8 +235,8 @@ public class StreamUtil {
* @param root 根节点根节点不允许被{@code filter}过滤 * @param root 根节点根节点不允许被{@code filter}过滤
* @param discoverer 下一层级节点的获取方法 * @param discoverer 下一层级节点的获取方法
* @param filter 节点过滤器不匹配的节点与以其作为根节点的子树将将会被忽略 * @param filter 节点过滤器不匹配的节点与以其作为根节点的子树将将会被忽略
* @return 包含根节点在内根节点所有层级结构中的节点组成的流
* @param <T> 元素类型 * @param <T> 元素类型
* @return 包含根节点在内根节点所有层级结构中的节点组成的流
* @see HierarchyIterator * @see HierarchyIterator
*/ */
public static <T> Stream<T> iterateHierarchies( public static <T> Stream<T> iterateHierarchies(
@ -254,8 +261,8 @@ public class StreamUtil {
* *
* @param root 根节点根节点不允许被{@code filter}过滤 * @param root 根节点根节点不允许被{@code filter}过滤
* @param discoverer 下一层级节点的获取方法 * @param discoverer 下一层级节点的获取方法
* @return 包含根节点在内根节点所有层级结构中的节点组成的流
* @param <T> 元素类型 * @param <T> 元素类型
* @return 包含根节点在内根节点所有层级结构中的节点组成的流
* @see HierarchyIterator * @see HierarchyIterator
*/ */
public static <T> Stream<T> iterateHierarchies( public static <T> Stream<T> iterateHierarchies(
@ -275,8 +282,10 @@ public class StreamUtil {
* @return 与指定断言匹配的元素组成的流 * @return 与指定断言匹配的元素组成的流
*/ */
public static <T> Stream<T> takeWhile(final Stream<T> source, final Predicate<? super T> predicate) { public static <T> Stream<T> takeWhile(final Stream<T> source, final Predicate<? super T> predicate) {
requireNonNull(source); if(null == source){
requireNonNull(predicate); return Stream.empty();
}
Objects.requireNonNull(predicate);
return createStatefulNewStream(source, TakeWhileSpliterator.create(source.spliterator(), predicate)); return createStatefulNewStream(source, TakeWhileSpliterator.create(source.spliterator(), predicate));
} }
@ -292,13 +301,14 @@ public class StreamUtil {
* @return 剩余元素组成的流 * @return 剩余元素组成的流
*/ */
public static <T> Stream<T> dropWhile(final Stream<T> source, final Predicate<? super T> predicate) { public static <T> Stream<T> dropWhile(final Stream<T> source, final Predicate<? super T> predicate) {
requireNonNull(source); if(null == source){
requireNonNull(predicate); return Stream.empty();
}
Objects.requireNonNull(predicate);
return createStatefulNewStream(source, DropWhileSpliterator.create(source.spliterator(), predicate)); return createStatefulNewStream(source, DropWhileSpliterator.create(source.spliterator(), predicate));
} }
// region 私有方法 // region ----- 私有方法
/* ================================================== 私有方法 =================================================== */
/** /**
* 根据 源流 新的Spliterator 生成新的流 * 根据 源流 新的Spliterator 生成新的流
@ -321,8 +331,5 @@ public class StreamUtil {
// 由于新流不与旧流的节点关联, 所以需要主动设置旧流的close方法, 哪怕几乎不可能有人在旧流上设置onClose操作 // 由于新流不与旧流的节点关联, 所以需要主动设置旧流的close方法, 哪怕几乎不可能有人在旧流上设置onClose操作
return newStream.onClose(source::close); return newStream.onClose(source::close);
} }
/* ============================================================================================================== */
// endregion // endregion
} }

View File

@ -212,7 +212,6 @@ public class CharSequenceUtil extends StrValidator {
* *
* <p> * <p>
* 注意{@link String#trim()}不同此方法使用{@link CharUtil#isBlankChar(char)} 来判定空白 因而可以除去英文字符集之外的其它空白如中文空格 * 注意{@link String#trim()}不同此方法使用{@link CharUtil#isBlankChar(char)} 来判定空白 因而可以除去英文字符集之外的其它空白如中文空格
* <p>
* <ul> * <ul>
* <li>去除字符串空格罗列相关如下</li> * <li>去除字符串空格罗列相关如下</li>
* <li>{@link StrUtil#trimPrefix(CharSequence)}去除头部空格</li> * <li>{@link StrUtil#trimPrefix(CharSequence)}去除头部空格</li>