2017-10-13 27 views
5

Không có câu lệnh "if", trừ khi bạn giải thích lý do tại sao nó không thể thực hiện mà không có.Java 8 forEach chỉ áp dụng cho một số?

Tôi thấy mình chỉ có thể hoạt động trên luồng bao xa. Tôi có phiền toái này:

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

ý tưởng tốt nhất của tôi cho làm thế nào để làm điều này mà không có "nếu" là

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

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

Có cách nào để làm điều này chỉ trong một chuỗi? Chi nhánh về cơ bản phải xảy ra trong luồng nếu có. Phương thức như forSome(predicate, lambda) sẽ hoạt động.

Không muốn "cuộn của riêng tôi" bất kỳ thứ gì. Tôi có thể sử dụng một "if" nhưng tôi đang cố gắng tìm hiểu cách thức thể hiện phong cách chức năng.

+0

là Optional.ifPresent thể chấp nhận được ? – VGR

+0

@VGR chính xác suy nghĩ của tôi :) – Eugene

+0

[Collectors.partitioningBy] (https://stackoverflow.com/a/30110890/3688648) có thể giúp nếu bạn muốn "phát" luồng của mình bằng 'Cube :: prop' – Felk

Trả lời

3

Không cần sử dụng map trả về cùng một yếu tố, khi bạn có peek. Các mã sau "cheats" bằng cách sử dụng một nhà điều hành ngắn mạch:

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

Tôi nghĩ rằng cách "hiện đại" sử dụng bắt buộc là ít có thể đọc được:

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

Điều đó giả định rằng 'thêm lời bình thường' trả về' boolean' – Arkadiy

+0

Không phải là điều gì đó sai với kiểu Optional.of (c)? có vẻ như làm tổ một lambda thay vì một chuỗi, tức là chữ "c" đầu tiên bị che khuất bởi chữ "c" thứ hai mặc dù chúng giống nhau. – djechlin

+3

@djechlin: Tất nhiên, khai báo một 'c' mới khi đã có' c' trong phạm vi không hoạt động. Bạn sẽ phải sử dụng một tên khác. – Holger

1

Bạn có thể thực hiện chức năng forSome của bạn trong sau cách:

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

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

    return c; 
} 

hơn bạn có thể sử dụng toán tử bản đồ để bơm này vào dòng:

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()); 

Chỉ cần để cung cấp cho một ví dụ về việc sử dụng chúng ta có thể lấy ví dụ sau:

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'})) 
      ); 

Bây giờ chúng ta có thể nếu đáp án đúng là 'A' và 'B' hơn chúng ta có thể truyền qua các đối tượng và thiết lập trạng thái kiểm tra thích hợp.

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())); 

in:

  • John: trôi qua thật
  • Andy: trôi qua thật
  • Mary: trôi qua thật
  • Jane: thông qua sai
Các vấn đề liên quan