【问题标题】:Converting to lambda expression with ForEach for a breaking for loop使用 ForEach 转换为 lambda 表达式以中断 for 循环
【发布时间】:2018-02-20 01:54:03
【问题描述】:

在 for 循环中具有以下破坏行为的代码:

package test;

import java.util.Arrays;
import java.util.List;

public class Test {

    private static List<Integer> integerList = Arrays.asList(1, 2, 3, 4);

    public static void main(String[] args) {
        countTo2(integerList);
    }

    public static void countTo2(List<Integer> integerList) {

        for (Integer integer : integerList) {
            System.out.println("counting " + integer);
            if (integer >= 2) {
                System.out.println("returning!");
                return;
            }
        }
    }
}

尝试使用 forEach() 用 Lambda 表达它会改变行为,因为 for 循环不再中断:

public static void countTo2(List<Integer> integerList) {

    integerList.forEach(integer -> {
        System.out.println("counting " + integer);
        if (integer >= 2) {
            System.out.println("returning!");
            return;
        }
    });
}

这实际上是有道理的,因为 return; 语句仅在 lambda 表达式本身(在内部迭代中)而不是整个执行序列中强制执行,所以有没有办法获得所需的行为(打破 for 循环) 使用 lambda 表达式?

【问题讨论】:

    标签: for-loop lambda foreach java-8


    【解决方案1】:

    您正在寻找的是short-circuit 终端操作,虽然这是执行此操作的方法:

    integerList.stream()
                .peek(x -> System.out.println("counting = " + x))
                .filter(x -> x >= 2)
                .findFirst()
                .ifPresent(x -> System.out.println("retunrning"));
    

    仅在处理sequential 流时才等效。一旦您添加parallelpeek 可能会显示您不期望的元素,因为没有定义processing order,但有encounter order - 这意味着元素将正确地馈送到终端操作。

    【讨论】:

    • 当然,它必须是顺序的,因为当条件匹配最小值时逻辑是短路的。
    【解决方案2】:

    以下代码在逻辑上与您的代码等价:

    public static void countTo2(List<Integer> integerList) {
        integerList.stream()
                   .peek(i -> System.out.println("counting " + i))
                   .filter(i -> i >= 2)
                   .findFirst()
                   .ifPresent(i -> System.out.println("returning!"));
    }
    

    如果您对任何事情感到困惑,请告诉我!

    【讨论】:

      【解决方案3】:

      我能想到的一种方法是使用anyMatch 和相反的方法:

      if (integerList.stream().noneMatch(val -> val >= 2)) {
          System.out.println("counting " + val);
      }
      
      if (integerList.stream().anyMatch(val -> val >= 2)) {
          System.out.println("returning!");
      }
      

      但在内部,这会迭代列表两次,我相信这不是非常理想的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-07
        相关资源
        最近更新 更多