如果我不需要任何终止值,如何终止流?

问题描述 投票:0回答:4

我有一个 Stream,它以

peek()
方法进行所有处理。我不需要流中的任何结果,但我需要终端操作才能进行处理。当然,我可以使用
count()
(或任何其他操作)终止流,但这会产生误导,就好像我需要流终止的一些结果一样。在这种情况下终止流的正确方法是什么?

以下是参考代码:

Stream<Collection<NetworkPart>> graphHolders = cutSegment.stream()
    .map(this::obtainCollectionFor);
for (NetworkPart part : edgesToNetworkParts.get(originalSegment)) {
    part.integrate(cutSegment);
    graphHolders = graphHolders.peek(gh -> gh.add(part));
}
graphHolders.count(); // Just to terminate
java java-stream
4个回答
5
投票

这就是我重写问题代码的方式:

Collection<NetworkPart> partsOwningEdge = edgesToNetworkParts.get(originalSegment);
partsOwningEdge.forEach(part -> part.integrate(cutSegment));
cutSegment.stream()
    .map(this::obtainCollectionFor)
    .forEach(gh -> gh.addAll(partsOwningEdge));

3
投票

如果只是“误导”让您烦恼,请尝试以下操作:

private static void terminateStream(Stream<?> stream) { 
    stream.forEach(e -> {});
}

我认为这会消除任何歧义:该方法有明确的目的,并且调用也很明确。当如下使用时,

public static void main(String[] args) {
    Stream<String> stream = Arrays.asList("a", "b", "c").stream();
    stream = stream.peek(str -> System.out.println(str));
    terminateStream(stream);
}

main方法会打印

a
b
c

这确实要求

stream
未关闭并且尚未被操作,否则会抛出
IllegalStateException


2
投票

您可以使用 allMatch() 作为终端操作,因为不需要对所有元素进行评估。


0
投票

调用“中间”流操作时要小心,尤其是与 peek 结合使用时。来自 JavaDoc:

“如果流实现能够优化部分或全部元素的生成(例如使用 findFirst 等短路操作,或者在 count 中描述的示例中),则不会为这些元素调用该操作元素。”

您的“终止”count()实际上根本阻止了 peek 被调用。

尝试运行此版本:

List<AtomicInteger> ints = List.of(new AtomicInteger(0), new AtomicInteger(0));

Stream<AtomicInteger> streamedInts = ints.stream();
for (int i=0; i<5; i++) {
    streamedInts = streamedInts.peek(AtomicInteger::incrementAndGet);
}
streamedInts.count();

ints.forEach(foo -> System.out.println(foo.get()));

然后将“.count()”调用替换为真正终止的内容,例如@DennisW

建议的“.forEach(e -> {})”

但是更好的方法是使用终止 forEach 来实际修改元素,正如 @gvlasov 已经建议的那样。

注意:我会评论另一个答案,但遗憾的是我还不允许:|

© www.soinside.com 2019 - 2024. All rights reserved.