有时在处理Java流()时,我发现自己需要使用非终端forEach()来触发副作用,但不会终止处理。
我怀疑我可以使用类似.map(item - > f(item))的方法执行此操作,其中方法f执行副作用并将项目返回到流中,但它似乎有点笨拙。
有没有一种标准的处理方式?
答案 0 :(得分:12)
是的。它被称为peek()
(来自JavaDoc的例子):
Stream.of("one", "two", "three", "four")
.peek(e -> System.out.println("Original value: " + e))
.filter(e -> e.length() > 3)
.peek(e -> System.out.println("Filtered value: " + e))
.map(String::toUpperCase)
.peek(e -> System.out.println("Mapped value: " + e))
.collect(Collectors.toList());
答案 1 :(得分:2)
不,没有。
peek()
仅在通过以下操作强制执行时才对所有元素进行操作。你能预测这段代码会打印什么吗?
public class Test
{
private static final AtomicBoolean FLAG = new AtomicBoolean(false);
private static void setFlagIfGreaterThanZero(int val)
{
if (val > 0) {
FLAG.set(true);
}
}
public static void main(String[] args)
{
FLAG.set(false);
// Test 1
IntStream.range(0, 10)
.peek(Test::setFlagIfGreaterThanZero)
.findFirst();
System.out.println(FLAG.get());
FLAG.set(false);
// Test 2
IntStream.range(0, 10)
.peek(Test::setFlagIfGreaterThanZero)
.sorted()
.findFirst();
System.out.println(FLAG.get());
FLAG.set(false);
// Test 3
IntStream.range(0, 10)
.boxed()
.peek(Test::setFlagIfGreaterThanZero)
.sorted()
.findFirst();
System.out.println(FLAG.get());
FLAG.set(false);
// Test 4
IntStream.range(0, 10)
.peek(Test::setFlagIfGreaterThanZero)
.filter(x -> x == 0)
.toArray();
System.out.println(FLAG.get());
}
}
答案是:
假
假
真正
真
如果您对Java Streams有充分的了解,那么输出可能很直观,但希望它也表明依赖peek()
作为中流forEach()
是一个非常糟糕的主意。
map()
也遭遇同样的问题。据我所知,没有Stream操作可以保证每个情况下的“处理每个元素而不采取快捷方式”的行为,而不依赖于先前和后续操作。
虽然这可能很痛苦,但Streams的短路行为是一个重要特征。您可能会发现这个优秀的答案非常有用:https://stackoverflow.com/a/32194320/507761