Java 8 forEach仅应用于某些?

时间:2017-10-13 14:43:23

标签: java java-8 java-stream

否"如果"请说明,除非您解释为什么没有它就无法做到。

我看到我只能在溪流上运行多远。我有这种麻烦:

List<Cube> revised =
    cubes.filter(p)
    .map(c -> f(c))
    .map(c -> {
        if(c.prop()) {
           c.addComment(comment);
        }
        return c;
    })
    .collect(Collectors.toList());

我最好的想法是如何在没有&#34; if&#34;是

List<Cube> revised = 
    cubes.filter(p)
    .map(c -> f(c));

revised
    .filter(Cube::prop)
    .forEach(c -> c.addComment(comment)); // can also map still

有没有办法只在一个链中做到这一点?如果是这样,分支基本上必须在流中发生。像forSome(predicate, lambda)这样的方法可行。

不想&#34;滚动我自己&#34;任何东西。我可以使用&#34; if&#34;但我试图了解表达性的功能风格。

2 个答案:

答案 0 :(得分:3)

当您拥有map时,无需使用返回相同元素的peek。以下代码&#34;作弊&#34;通过使用短路运营商:

cubes.filter(p)
    .map(c -> f(c))
    .peek(c -> c.prop() && c.addComment(comment))

我认为&#34;现代&#34;使用Optional的方式可读性差得多:

cubes.filter(p)
    .map(c -> f(c))
    .peek(c -> Optional.of(c).filter(Cube::prop).ifPresent(c -> c.addComment(comment)))

答案 1 :(得分:1)

您可以通过以下方式实施forSome功能:

public static <T> T forSome(T c, Predicate<T> condition, Consumer<T> extraBehaviour) {

    if (condition.test(c)) {
        extraBehaviour.accept(c);
    }

    return c;
}

您可以使用map运算符将其注入流中:

   List<Cube> revised = cubes.stream().filter(p)
            .map(c -> f(c))
            .map(c -> forSome(c, Cube::prop, cube -> cube.addComment("my comment 2")))
            .collect(Collectors.toList());

为了给出另一个使用示例,我们可以采用以下示例:

class StudentExam {
    private final String studentName;
    private final List<Character> answers;
    private boolean passed = false;


    StudentExam(String studentName, List<Character> answers) {
        this.studentName = studentName;
        this.answers = answers;
    }

    public void markAsPassed() {
        this.passed = true;
    }

    public boolean isPassed() {
        return passed;
    }

    public Character getAnswer(int index) {
        return answers.get(index);
    }

    public String getStudentName() {
        return studentName;
    }
}

   List<StudentExam> results = asList(
            new StudentExam("John", asList(new Character[] {'A', 'B'})),
            new StudentExam("Andy", asList(new Character[] {'A', 'C'})),
            new StudentExam("Mary", asList(new Character[] {'B', 'B'})),
            new StudentExam("Jane", asList(new Character[] {'C', 'D'}))
            );

现在我们可以正确答案是&#39; A&#39;和&#39; B&#39;比我们可以流过对象并设置适当的考试状态。

    results.stream()
            .map(examResult -> forSome(
                    examResult,
                    er -> er.getAnswer(0).equals('A') || er.getAnswer(1).equals('B'),
                    StudentExam::markAsPassed))
            .forEach(studentExam -> 
                     studentExam.getStudentName() + " passed: " + studentExam.isPassed()));

打印:

  • 约翰:传递真实
  • 安迪:通过了
  • 玛丽:传递真实
  • 简:通过了假