java foreach 中止_从Java 8stream中断或返回forEach?

如果你需要这个,你不应该使用forEach ,而应该使用其他方法之一。 哪一个取决于你的目标是什么。

例如,如果这个循环的目标是find匹配某个谓词的第一个元素:

Optional result = someObjects.stream().filter(obj -> some_condition_met).findFirst();

(注意:这不会迭代整个集合,因为stream被懒惰地评估 – 它会停在匹配条件的第一个对象上)。

如果您只想知道集合中是否存在条件为true的元素,则可以使用anyMatch :

boolean result = someObjects.stream().anyMatch(obj -> some_condition_met);

这forEach() 是可能的。 解决scheme不好,但它是可能的。

警告 :您不应该将其用于控制​​业务逻辑,而是纯粹用于处理执行forEach()期间发生的exception情况。 如资源突然停止访问,其中一个被处理的对象违反合同(例如,合同中说,stream中的所有元素不能为null但突然意外地其中一个为null )等等。

根据Iterable.forEach()的文档:

对Iterable每个元素执行给定的操作, 直到处理完所有元素,或者操作引发exception …将由操作引发的exception中继给调用者。

所以你抛出一个exception,将立即打破内部循环。

代码将是这样的 – 我不能说我喜欢它,但它的作品。 您创build了自己的类BreakException ,它扩展了RuntimeException 。

try { someObjects.forEach(obj -> { // some useful code here if(some_exceptional_condition_met) { throw new BreakException(); } } } catch (BreakException e) { // here you know that your condition has been met at least once }

请注意, try...catch 不在 lambdaexpression式周围,而是围绕整个forEach()方法。 为了使其更清晰可见,请参阅下面的代码转录,以更清晰地显示它:

Consumer super SomeObject> action = obj -> { // some useful code here if(some_exceptional_condition_met) { throw new BreakException(); } }); try { someObjects.forEach(action); } catch (BreakException e) { // here you know that your condition has been met at least once }

下面你可以find我在一个项目中使用的解决scheme。 相反forEach只使用allMatch :

someObjects.allMatch(obj -> { return !some_condition_met; });

要么你需要使用一个方法,使用谓词表示是否继续(所以它有中断), 或者你需要抛出一个exception – 这当然是一个非常丑陋的方法。

所以你可以写这样的forEachConditional方法:

public static void forEachConditional(Iterable source, Predicate action) { for (T item : source) { if (!action.test(item)) { break; } } }

而不是Predicate ,你可能想要用相同的一般方法定义你自己的函数接口(东西取一个T并返回一个bool ),但是用更清楚地表示期望的名称 – Predicate在这里并不理想。

lambda中的返回等于for-each中的继续,但没有与break相等的效果。 你可以做一个返回继续:

someObjects.forEach(obj -> { if (some_condition_met) { return; } })

你可以使用java8 + rxjava 。

//import java.util.stream.IntStream; //import rx.Observable; IntStream intStream = IntStream.range(1,10000000); Observable.from(() -> intStream.iterator()) .takeWhile(n -> n < 10) .forEach(n-> System.out.println(n));

为了在并行操作中获得最大性能,可以使用类似于findFirst()的findAny ()。

Optional result = someObjects.stream().filter(obj -> some_condition_met).findAny();

但是,如果需要稳定的结果,请使用findFirst()。

还要注意匹配的模式(anyMatch()/ allMatch)只会返回布尔值,不会得到匹配的对象。

我已经完成了这样的事情

private void doSomething() { List actions = actionRepository.findAll(); boolean actionHasFormFields = actions.stream().anyMatch(actionHasMyFieldsPredicate()); if (actionHasFormFields){ context.addError(someError); } } } private Predicate actionHasMyFieldsPredicate(){ return action -> action.getMyField1() != null; }

你可以使用peek(..)和anyMatch(..)的混合来实现。

用你的例子:

someObjects.stream().peek(obj -> { }).anyMatch(obj -> !);

或者只写一个通用的util方法:

public static void streamWhile(Stream stream, Predicate super T> predicate, Consumer super T> consumer) { stream.peek(consumer).anyMatch(predicate.negate()); }

然后使用它,像这样:

streamWhile(someObjects.stream(), obj -> , obj -> { });

用JDK提供的API来做这件事并不容易。 但是我们可以通过AbacusUtil来完成 。 这里是示例代码:

Stream.of("a", "b", "c", "d", "e").peek(N::println) // .forEach("", (r, e) -> r + e, (e, r) -> e.equals("c")); // print: abc

披露:我是AbacusUtil的开发者。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值