尽早终止Iterable.forEach

Val*_*len 2 java lambda iterable java-8

我有一套和一个方法:

private static Set<String> set = ...;
public static String method(){
    final String returnVal[] = new String[1];
    set.forEach((String str) -> {
        returnVal[0] += str;
        //if something: goto mark
    });
    //mark
    return returnVal[0];
}
Run Code Online (Sandbox Code Playgroud)

我可以在lambda中终止forEach(使用或不使用例外)吗?我应该使用匿名课吗?

我能做到这一点:

set.forEach((String str) -> {
     if(someConditions()){
         returnVal[0] += str;
     }
});
Run Code Online (Sandbox Code Playgroud)

但是浪费时间.

使用stream.reduce实现

return set.parallelStream().reduce((output, next) -> {
    return someConditions() ? next : output;
}).get(); //should avoid empty set before
Run Code Online (Sandbox Code Playgroud)

我正在寻找最快的解决方案,因此如果它们足够快,那么每个循环的异常和"真实"是可以接受的.

Mak*_*oto 6

即使我不完全确定你想要完成什么,我也不愿回答这个问题,但简单的答案是否定的,你不能forEach在处理元素的中途终止它.

官方Javadoc声明它是一个适用于流中所有元素的终端操作.

对此流的每个元素执行操作.

这是终端操作.

如果要将结果收集到单个结果中,则需要使用简化.

一定要考虑流正在做什么.它作用于其中包含的所有元素 - 如果它沿途被过滤,则链中的每个步骤都可以说对其流中的所有元素起作用,即使它是原始元素的子集.


如果你好奇为什么简单地把一个return没有任何影响,这里是实现forEach.

default void forEach(Consumer<? super T> action) {
    Objects.requireNonNull(action);
    for (T t : this) {
        action.accept(t);
    }
}
Run Code Online (Sandbox Code Playgroud)

消费者被明确传入,这与完成的实际迭代无关.我想你可以抛出异常,但是当可能存在更优雅的解决方案时,这会很俗气.