2017-06-26 37 views
10

Tôi đang sử dụng .peek() trong luồng của tôi nhưng nó được tán thành, thật đáng buồn là tôi không thể tìm được giải pháp.Việc sử dụng .peek() trong java 8 suối

phiên bản đơn giản:

static boolean fooAddTester(int size) { 
    Foo foo = new foo(); //data structure 

    return IntStream.range(0, size). 
      .peek(i -> synchronized(r){foo.add(i)}) 
      .allMatch(e -> foo.isLegal()); 
} 

những gì tôi cần làm là để lặp qua các IntStream và để kiểm tra sau mỗi lần chèn nếu cấu trúc dữ liệu foo là hợp pháp. Đây là một cách logic tương đương với:

static boolean fooAddTester(int size) { 
    Foo foo = new foo(); //data structure 

    for(int i=0; i<size; i++){ 
     foo.add(i); 
     if(!foo.isLegal()) 
      return false; 
    return true; 
} 

Tuy nhiên nó là phức tạp hơn và tôi đang cố gắng sử dụng suối để đơn giản hóa và học hỏi.

Một cách để làm như vậy mà không sử dụng .peek() là thế này: mà không làm việc - nhưng tôi chỉ "di chuyển" các vấn đề để .allMatch():

return IntStream.range(0, size). 
      .allMatch(i -> { 
       synchronized(r){foo.add(i)}; 
       foo.isLegal(); 
      )}; 

Vấn đề của tôi là rất giống với this question, diffrence là tôi kiểm tra mọi lúc để giải pháp không hoạt động.

Vì vậy, câu hỏi của tôi là:

  • .peek() thực sự chỉ để gỡ lỗi hoặc tôi có thể sử dụng nó theo cách này?
  • Có giải pháp nào tốt hơn không?
  • Tôi có nên sử dụng giải pháp thứ hai của mình không?

Tôi đang tìm giải pháp đúng, không phải giải pháp làm việc, tất cả các mã đó đều đang hoạt động.

+2

này có thể giúp: https://softwareengineering.stackexchange.com/questions/308977/is-it-an-antipattern-to-use-peek-to-modify-a-stream-element – Rjiuk

+0

bạn muốn để kiểm tra điều kiện 'sau mỗi lần chèn'; đó là dựa vào tác dụng phụ và nó nên tránh. – Eugene

+1

'đồng bộ' sẽ không giúp bạn nhiều btw - nó sẽ đảm bảo rằng chỉ có một phần tử tại một thời điểm được đưa vào 'foo'; nhưng nó sẽ không đảm bảo * phần tử * nào được đặt vào foo, vì không có thứ tự xử lý trong trường hợp của một luồng song song – Eugene

Trả lời

3

tài liệu của Stream#peek đã đề cập như dưới đây, và chủ yếu không phải là hoàn toàn:

Phương pháp này tồn tại chủ yếu để hỗ trợ gỡ lỗi, nơi bạn muốn để xem các yếu tố như họ chảy qua một điểm nhất định trong một đường ống

@Holger đã trả lời câu hỏi này hoàn toàn:

các nhất điều hữu ích mà bạn có thể làm với peektìm hiểu dù một yếu tố dòng đã được xử lý.

và một số tác dụng phụ mà anh ta cũng đã chỉ ra trong câu trả lời của mình, hoạt động peek tùy thuộc vào thao tác đầu cuối nào được gọi.vì vậy khi sử dụng peek nội bộ, bạn nên cẩn thận.

vì vậy cách chính xác chỉ sử dụng vòng lặp for-each, vì Stream#collect không hỗ trợ short-circuiting operation.

cách tùy chọn đang sử dụng peek vì bạn có thể tự mình kiểm soát luồng. và bạn cần phải xóa khối synchornized, không cần thiết ở đây.

return IntStream.range(0, size).peek(foo::add).allMatch(__ -> Foo.isLegal(foo)); 
+4

vâng, 'điều hữu ích nhất mà bạn có thể làm với peek là tìm hiểu xem liệu một yếu tố luồng đã được xử lý hay chưa.', nhưng bằng cách ghi nhật ký, không dựa vào các tác dụng phụ. Ngay sau khi bạn thêm 'song song' điều này sẽ phá vỡ theo những cách bí ẩn. đồng bộ sẽ đảm bảo rằng chỉ có một phần tử tại một thời điểm được xử lý, nhưng ngay cả khi đó bạn không biết phần tử nào, có * thứ tự xử lý *. – Eugene

+0

@Eugene nhưng tôi muốn nói rằng OP có thể kiểm soát cách tạo, tiêu thụ, vận hành một luồng. do đó, không có vấn đề ở đây. –

+0

Tôi đã thêm 'synchornized' ban đầu để sử dụng' parallel() '. Cảm ơn rất nhiều cho câu trả lời của bạn! –

2

tôi có thể nghĩ đến chỉ là một cách duy nhất để làm điều đó nếu bạn thực sự muốn sử dụng các hoạt động dòng khác trước logic của bạn, nhưng tôi không thực sự là một fan hâm mộ lớn của nó ...

boolean result = true; 
    try { 
     IntStream.range(0, 10) 
       .forEachOrdered(x -> { 
        foo.add(x); 
        if (!Foo.isLegal(foo)) { 
         throw new RuntimeException("just because"); 
        } 
       }); 
    } catch (RuntimeException re) { 
     result = false; 
    } 

    System.out.println(result); 

Rõ ràng bạn cần phải thay thế RuntimeException bằng một số loại ngoại lệ của bạn.

Các vấn đề liên quan