Java 8 Lambdas - 按位和操作

xan*_*gor 16 java lambda for-loop bitwise-operators java-8

我目前正在解决使用Java 8中的Lambdas使用按位运算的转换for循环的问题.

给定一组复杂的条目,循环需要遍历所有条目并在它们上调用给定的方法(方法返回布尔值).然后,返回结果.

换句话说,我需要在所有条目上调用该方法并存储结果.这背后的原因是每个条目独立地执行复杂的操作并且必须执行.最终结果是结果的组合.

代码段:

boolean areAllSuccessful = true;
for (SomeEntry entry : entries) {
     areAllSuccessful = areAllSuccessful & entry.doComplexAction(); // keep calling the method on other entries regardless of the result.
}

return areAllSuccessful;
Run Code Online (Sandbox Code Playgroud)

问题是Java 8中的Lambda函数通常执行短路操作(一旦检测到错误条目,"循环"中断并返回错误结果).

到目前为止,我最好的解决方案是使用map/filter/count组合:

return entries
       .stream()
       .map(entry -> entry.doComplexAction())
       .filter(result -> result == false)
       .count() > 0
Run Code Online (Sandbox Code Playgroud)

有更聪明/更清洁的方式吗?

谢谢!

Eug*_*ene 28

不应该看起来像这样:

boolean areAllSuccessful = entries.stream()
   .map(entry -> entry.isSuccessful())
   .reduce(Boolean.TRUE, Boolean::logicalAnd);
Run Code Online (Sandbox Code Playgroud)

  • ...然后等待下一个开发人员看到代码并说"嘿,这看起来像'allMatch`的完美任务"...... (14认同)
  • @Holger Bohemian 刚刚使用 `allMatch` 发布了一个答案:http://stackoverflow.com/a/42277670/ (2认同)
  • 我发现有一个'Boolean :: logicalAnd`但仍然是`entry - > entry.isSuccessful()`有点令人不安.后者不能写成'SomeEntry :: isSuccessful`吗? (2认同)

Boh*_*ian 19

最新,最有效的方法是使用方法引用 allMatch()

return entries.stream().allMatch(SomeEntry::isSuccessful);
Run Code Online (Sandbox Code Playgroud)

如果您有1000个元素,请考虑使用parallelStream().

这不处理每个元素(它在第一个元素返回false),所以如果你的isSuccessful()方法有副作用,那就是一个坏名字,你应该重命名它或重构代码以在process()(或类似的)方法中执行副作用并且isSuccessful()返回结果,抛出一个IllegalStateExceptionif process()还没有被调用过.

如果你不重构,一些开发人员(包括你)会在isSuccessful()没有意识到"做东西"的情况下打电话,这可能是坏事.

  • 这就是重点,OP不想在第一个假的时候停止.这就是他在评论中所说的:*实际上我已经隐藏了一些问题.isSuccessful()调用背后的操作实际上是复杂的独立系统操作,应该不管彼此执行.最终结果是所有回复的组合* (5认同)
  • 我的回答解释了`allMatch()`解决方案,我的评论解释了``isSuccessful()`这个名字真的很糟糕.但你的答案解释了两者并且更清楚.+1. (3认同)

wal*_*len 11

map()如果你打算使用,你真的不需要count():

return !(entries
        .stream()
        .filter(entry -> !entry.isSuccessful())
        .count() > 0);
Run Code Online (Sandbox Code Playgroud)

如果该方法isSuccessful()没有副作用,并且您需要知道的是所有条目都成功,您可以使用allMatch():

return entries
        .stream()
        .allMatch(entry -> entry.isSuccessful());
Run Code Online (Sandbox Code Playgroud)

这确实是一个短路操作,将返回false只要它找到其中一个条目isSuccessful()false,不消耗整个流,除非必要的.但你已经评论说,这isSuccesful()实际上意味着"做一些复杂的行动然后告诉我它们是否成功",所以它不适用.