.peek()在Java8流中的使用
我正在我的流中使用.peek(),但它不受欢迎,很遗憾我找不到解决方案 简化版:.peek()在Java8流中的使用,java,java-8,java-stream,Java,Java 8,Java Stream,我正在我的流中使用.peek(),但它不受欢迎,很遗憾我找不到解决方案 简化版: static boolean fooAddTester(int size) { Foo foo = new foo(); //data structure return IntStream.range(0, size). .peek(i -> synchronized(r){foo.add(i)}) .allMatch(e -> foo.
static boolean fooAddTester(int size) {
Foo foo = new foo(); //data structure
return IntStream.range(0, size).
.peek(i -> synchronized(r){foo.add(i)})
.allMatch(e -> foo.isLegal());
}
我需要做的是迭代IntStream,并在每次插入后检查,看foo数据结构是否合法。
这在逻辑上等同于:
static boolean fooAddTester(int size) {
Foo foo = new foo(); //data structure
for(int i=0; i<size; i++){
foo.add(i);
if(!foo.isLegal())
return false;
return true;
}
我的问题非常类似于,不同之处在于我每次都在检查,所以解决方案不起作用
因此,我的问题是:
真的只是为了调试,还是我可以这样使用它.peek()
- 有没有更好的解决办法
- 我应该使用第二种解决方案吗
我正在寻找一个正确的解决方案,而不是一个有效的解决方案,所有这些代码都已经在运行。如果您真的想在逻辑之前使用其他流操作,我只能想到一种方法来实现它,但我不是它的忠实粉丝
boolean result = true;
try {
IntStream.range(0, 10)
.forEachOrdered(x -> {
foo.add(x);
if (!Foo.isLegal(foo)) {
throw new RuntimeException("just because");
}
});
} catch (RuntimeException re) {
result = false;
}
System.out.println(result);
显然,您需要用某种异常替换
RuntimeException
Stream#peek的文档如下所述,主要不是绝对的:
此方法的存在主要是为了支持调试,您希望在元素流过管道中的某个点时看到这些元素
绝对回答了这个问题:
使用peek
可以做的最有用的事情是找出流元素是否已被处理
他在回答中也指出了一些副作用,peek
操作取决于调用哪个终端操作。因此,在内部使用peek
时,您应该小心
因此正确的方法是对每个循环使用,因为Stream#collect
不支持
可选的方法是使用peek
,因为您可以自己控制流。您需要删除synchornized
块,这里不需要它
return IntStream.range(0, size).peek(foo::add).allMatch(__ -> Foo.isLegal(foo));
这可能会有帮助:您希望在每次插入后检查条件;这依赖于副作用,应该避免。顺便说一句,synchronized
对您没有多大帮助-它将保证每次只在foo
中放入一个元素;但它不能保证将哪个元素放入foo中,因为在并行流的情况下没有处理顺序。对于“新手”来说,什么是r
?你为什么要在上面同步?您的流代码与循环不匹配。您正在对int
值进行流式处理,因此需要使用static
方法Foo.isLegal(int)
使编译器接受第一个代码段。在最后一个代码段中,您正在不允许方法引用的位置使用方法引用Foo::isLegal
。显然,您从未尝试过这些方法中的任何一种。是的,使用peek可以做的最有用的事情是找出流元素是否已被处理。
,但是通过日志记录,而不是依赖于副作用。只要你添加parallel
,这将以神秘的方式中断。synchronized将确保一次只处理一个元素,但即使这样,您也不知道是哪个元素,有处理顺序。@Eugene但我想说OP可以控制如何创建、使用和操作流。所以这里没有问题。我添加了synchornized
,最初是为了使用parallel()
。非常感谢你的回答!
return IntStream.range(0, size).peek(foo::add).allMatch(__ -> Foo.isLegal(foo));