我在流中使用.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.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()
的情况下实现同样的方法是这样的:这确实有效--但我只是将问题转移到.allMatch()
上
return IntStream.range(0, size).
.allMatch(i -> {
synchronized(r){foo.add(i)};
foo.isLegal();
)};
我的问题与这个问题非常相似,不同之处在于我每次都在检查,所以解决方案不起作用。
所以我的问题是:
.peek()
真的只用于调试还是我可以以这种方式使用它?我正在寻找一个正确的解决方案,而不是一个有效的解决方案,所有这些代码都已经开始工作了。
发布于 2017-06-26 04:38:43
Stream#peek
的文档如下所述,主要不是绝对
此方法主要存在(主要是)以支持调试,其中您希望看到元素流经管道中的某个点时的情况。
@Holger完全回答了这个问题:
使用最有用的是,查找是否已处理流元素的。
他在回答中也指出了一些副作用,peek
操作取决于调用了哪个终端操作。因此,在内部使用peek
时,您应该小心。
所以正确的方法是只使用for-each
循环,因为Stream#collect
不支持短路操作。
可选的方法是使用peek
,因为您可以自己控制流。您需要删除synchornized
块,这在这里是不必要的。
return IntStream.range(0, size).peek(foo::add).allMatch(__ -> Foo.isLegal(foo));
发布于 2017-06-26 04:19:28
如果你真的想在你的逻辑之前使用其他的流操作,我只能想出一个方法来做,但我并不是它的忠实粉丝.
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
。
https://stackoverflow.com/questions/44759090
复制