我们能否以某种方式将 Java 中的流拆分为不超过 N 个元素的子流? 例如
Stream<Integer> s = Stream.of(1,2,3,4,5);
Stream<Stream<Integer>> separated = split(s, 2);
// after that separated should contain stream(1,2), stream(3,4), stream(5)
按两个流拆分的解决方案仅适用于 2 个流,对于 N 个流来说也是如此,将非常丑陋且只写。
您无法轻松直接地将
Stream
拆分为 2 个或更多 Streas
。程序上唯一的方法是由情侣将元素收集到List
,然后再次将它们映射回Stream
:
Stream<Integer> s = Stream.of(1,2,3,4,5);
List<Integer> list = s.collect(Collectors.toList());
int size = list.size();
List<List<Integer>> temp = new ArrayList<>();
List<Integer> temp2 = new ArrayList<>();
int index = 0;
for (int i=0; i<size; i++) {
temp2.add(list.get(i));
if (i%2!=0) {
temp.add(temp2);
temp2 = new ArrayList<>();
}
if (i == size - 1) {
temp.add(temp2);
}
}
Stream<Stream<Integer>> stream = temp.stream().map(i -> i.stream());
如您所见,这是一条非常长的路,而且不值得。将这些对存储在
List
中而不是 Stream
中不是更好吗? java-stream API 不用于数据存储,而是用于数据处理。
例如:
<T> Stream<Stream<T>> split(Stream<T> stream, int n) {
final var it = stream.iterator();
final Stream.Builder<Stream<T>> result = Stream.builder();
while (it.hasNext()) {
final Stream.Builder<T> buf = Stream.builder();
for (int i = 0; i < n && it.hasNext(); i++) {
buf.accept(it.next());
}
result.accept(buf.build());
}
return result.build();
}
Stream<Integer> s = Stream.of(1,2,3,4,5);
Stream<Stream<Integer>> separated = split(s, 2);
separated.map(x -> x.collect(Collectors.toList())).forEach(System.out::println);
[1, 2]
[3, 4]
[5]
JEP 461:流收集器Java 22 预览语言功能添加了对将流分区为给定大小的列表的内置支持。然后可以将这些列表映射到流中。
// A stream containing 2 (or less) element streams: [[1, 2], [3, 4], [5]]
Stream<Stream<Integer>> separated = Stream.of(1, 2, 3, 4, 5)
.gather(Gatherers.windowFixed(2))
.map(Collection::stream);
这使用新的 方法和新的内置 Gatherers.windowFixed
收集器将初始 Stream<T>
转换为
Stream<List<T>>
。然后使用
Stream<Stream<T>>
将其转换为 Stream.map
,并将 Collection::stream
作为映射函数。
Java文档将输入元素流转换为输出元素流的中间操作,可以选择在到达上游末尾时应用最终操作。 […]:[…]
聚集操作的例子有很多,包括但不限于:将元素分组(窗口函数);对连续相似的元素进行去重;增量累加功能(前缀扫描);增量重新排序功能等。类提供了常见收集操作的实现。
返回一个流,其中包含将给定收集器应用于该流的元素的结果。
返回一个收集器,它将元素收集到固定大小的窗口中——遇到有序的元素组。如果流为空,则不会生成任何窗口。最后一个窗口包含的元素可能少于提供的窗口大小。示例:
// will contain: [[1, 2, 3], [4, 5, 6], [7, 8]] List<List<Integer>> windows = Stream.of(1,2,3,4,5,6,7,8).gather(Gatherers.windowFixed(3)).toList();