如何实现 Java 流?
How to implement a Java stream?
我想实现一个Stream<T>
。
我不想只使用 implements Stream<T>
,因为我必须实现大量方法。
这可以避免吗?
更具体地说,我如何流式传输 t1
、t2
和 t3
例如:
class Foo<T> {
T t1, t2, t3;
Foo(T t1, T t2, T t3) {
this.t1 = t1;
this.t2 = t2;
this.t3 = t3;
}
}
JDK对Stream
的标准实现是内部classjava.util.stream.ReferencePipeline
,不能直接实例化。
相反,您可以使用 java.util.stream.Stream.builder()
、java.util.stream.StreamSupport.stream(Spliterator<T>, boolean)
和各种 1, 2 其他静态工厂方法来创建默认实现的实例。
使用拆分器可能是最强大的方法,因为它允许您延迟提供对象,同时如果您的源可以分为多个块,还可以实现高效的并行化。
此外,如果您需要实现自己的有状态中间操作,您还可以将流转换回拆分器,将它们包装在自定义拆分器中,然后将它们转换回流。例如由于标准 API 的缺陷 - 例如大多数可用的中间操作 are not allowed to be stateful.
See 。
原则上您可以编写自己的流接口实现,但这会非常乏味。
您通常不需要编写自己的流class。相反,您可以通过现有方法创建流。例如,这里是如何创建一个值为 1, 100 的流:
AtomicInteger n = new AtomicInteger(0);
Stream<Integer> stream = Stream.generate(() -> n.incrementAndGet()).limit(100);
所以在这里我们创建了一个无限的整数流:1、2、3,....然后我们在那个无限流上使用 limit(100)
来取回一个包含 100 个元素的流。
为清楚起见,如果您想要一个整数流(以固定间隔),您应该使用 IntStream.range()
。这只是一个示例,展示了如何使用 Stream.generate()
定义流,这为您提供了更大的灵活性,因为它允许您使用任意逻辑来确定流的元素。
其他人回答了如何提供通用 Stream
实现。关于您的特定要求,只需执行以下操作:
class Foo<T> {
T t1, t2, t3;
Foo(T t1, T t2, T t3) {
this.t1 = t1;
this.t2 = t2;
this.t3 = t3;
}
Stream<T> stream() {
return Stream.of(t1, t2, t3);
}
}
如果您因为需要自定义 close()
逻辑而想要创建自己的 Stream,最简单的解决方案是从迭代器创建一个 Stream,然后调用 onClose(Runnable)
。例如,要通过 Jackson 从 Reader 流式传输:
MappingIterator<?> values = objectMapper.reader(type).readValues(reader);
return StreamSupport
.stream(Spliterators.spliteratorUnknownSize(values, Spliterator.ORDERED), false)
.onClose(() -> {
try {
reader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
});
为了完整起见,因为我没有直接在 SO 的答案中找到这个:
如果你想将现有的 Iterator 转换为 Stream(例如,因为你想连续生成元素),请使用:
StreamSupport.stream(
Spliterators.spliterator(myIterator, /* initial size*/ 0L, Spliterator.NONNULL),
/* not parallel */ false);
我发现这有点难找,因为你需要了解 StreamSupport、Spliterators 和 Spliterator
我想实现一个Stream<T>
。
我不想只使用 implements Stream<T>
,因为我必须实现大量方法。
这可以避免吗?
更具体地说,我如何流式传输 t1
、t2
和 t3
例如:
class Foo<T> {
T t1, t2, t3;
Foo(T t1, T t2, T t3) {
this.t1 = t1;
this.t2 = t2;
this.t3 = t3;
}
}
JDK对Stream
的标准实现是内部classjava.util.stream.ReferencePipeline
,不能直接实例化。
相反,您可以使用 java.util.stream.Stream.builder()
、java.util.stream.StreamSupport.stream(Spliterator<T>, boolean)
和各种 1, 2 其他静态工厂方法来创建默认实现的实例。
使用拆分器可能是最强大的方法,因为它允许您延迟提供对象,同时如果您的源可以分为多个块,还可以实现高效的并行化。
此外,如果您需要实现自己的有状态中间操作,您还可以将流转换回拆分器,将它们包装在自定义拆分器中,然后将它们转换回流。例如由于标准 API 的缺陷 - 例如大多数可用的中间操作 are not allowed to be stateful.
See
原则上您可以编写自己的流接口实现,但这会非常乏味。
您通常不需要编写自己的流class。相反,您可以通过现有方法创建流。例如,这里是如何创建一个值为 1, 100 的流:
AtomicInteger n = new AtomicInteger(0);
Stream<Integer> stream = Stream.generate(() -> n.incrementAndGet()).limit(100);
所以在这里我们创建了一个无限的整数流:1、2、3,....然后我们在那个无限流上使用 limit(100)
来取回一个包含 100 个元素的流。
为清楚起见,如果您想要一个整数流(以固定间隔),您应该使用 IntStream.range()
。这只是一个示例,展示了如何使用 Stream.generate()
定义流,这为您提供了更大的灵活性,因为它允许您使用任意逻辑来确定流的元素。
其他人回答了如何提供通用 Stream
实现。关于您的特定要求,只需执行以下操作:
class Foo<T> {
T t1, t2, t3;
Foo(T t1, T t2, T t3) {
this.t1 = t1;
this.t2 = t2;
this.t3 = t3;
}
Stream<T> stream() {
return Stream.of(t1, t2, t3);
}
}
如果您因为需要自定义 close()
逻辑而想要创建自己的 Stream,最简单的解决方案是从迭代器创建一个 Stream,然后调用 onClose(Runnable)
。例如,要通过 Jackson 从 Reader 流式传输:
MappingIterator<?> values = objectMapper.reader(type).readValues(reader);
return StreamSupport
.stream(Spliterators.spliteratorUnknownSize(values, Spliterator.ORDERED), false)
.onClose(() -> {
try {
reader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
});
为了完整起见,因为我没有直接在 SO 的答案中找到这个: 如果你想将现有的 Iterator 转换为 Stream(例如,因为你想连续生成元素),请使用:
StreamSupport.stream(
Spliterators.spliterator(myIterator, /* initial size*/ 0L, Spliterator.NONNULL),
/* not parallel */ false);
我发现这有点难找,因为你需要了解 StreamSupport、Spliterators 和 Spliterator