2017-01-09 36 views
6

Gần đây tôi đã tìm hiểu về các luồng trong Java 8 và bắt đầu làm việc với chúng. Bây giờ tôi có một câu hỏi liên quan đến phương pháp groupingBy thu:Java 8 GroupingBy vào Peek

Thông thường tôi làm việc với .NET, vì vậy tôi so sánh (biết họ không giống nhau) Java Stream<T> với .NET IEnumerable<T>. Sau so sánh này, List<T> các yếu tố cửa hàng và cụ thể Stream/IEnumerable áp dụng các hoạt động. Một ví dụ:

C#:

elements.Where(x => x.Value == 5).ToList(); 

Java:

elements.stream().filter(x -> x.getValue() == 5).collect(Collectors.toList()); 

Trong cả hai ví dụ, tôi bắt đầu với một danh sách, xác định hoạt động (một bộ lọc trong ví dụ này) và thu thập kết quả để lưu trữ nó (trong một danh sách mới trong ví dụ này).

Bây giờ tôi có một trường hợp phức tạp hơn:

data.stream() 
    .map(...).filter(...) // Some operations 
    .collect(groupingBy(Chunk::getName, summingLong(Chunk::getValue))); 

Kết quả của truy vấn này là một Map<String, Long> và tôi có thể làm việc với điều này, nhưng cho phép nói, tôi muốn tiếp tục với các dữ liệu này thay vì lưu trữ nó. Cách tiếp cận hiện tại của tôi là tầm thường:

... 
    .collect(groupingBy(Chunk::getName, summingLong(Chunk::getValue))) 
    .entrySet().stream(). 
    .map(...) // Do more operations 

Nhưng theo cách này, tôi rời khỏi luồng, lưu kết quả đầu tiên vào Bản đồ và mở luồng mới để tiếp tục. Có cách nào để nhóm mà không có người thu thập, để tôi có thể "ở lại" trong luồng không?

+1

Vì bạn đang nhóm, bạn cần phải đi đến cửa hàng trung gian - bạn nên làm gì khi nhóm giá trị ở đầu luồng với giá trị ở cuối? Bạn sẽ cần phải xử lý "mọi thứ", lưu trữ nó cho đến khi bạn chắc chắn không có gì nhiều hơn để nhóm với. Vì vậy, nội bộ, Java sẽ phải (/ có thể?) Đặt mọi thứ trong một bản đồ (hoặc một số cấu trúc tương tự) anyway; những gì quá xấu về việc này làm cho mình? –

+0

Nó không thực sự là một vấn đề, tôi có thể sống với cách tiếp cận tầm thường của tôi, nhưng trong tất cả các hoạt động dòng khác của tôi có một dòng rõ ràng giữa việc có một 'List' và có một' Stream'. Tôi mở nó ra, vận hành và thu thập nó. Bây giờ có một bản đồ, được mở ra cho một dòng mới, vì vậy tôi đã tự hỏi nếu nó có thể với một cách tiếp cận khác. –

+0

Có lẽ tôi đã bối rối bởi nền .NET của tôi. Ở đó bạn có thể thực hiện bất kỳ thao tác nào trên một 'IEnumerable' và cuối cùng bạn thu thập kết quả của mình thông qua' ToList', 'ToArray',' ToDictionary' hoặc bằng cách lặp qua nó. –

Trả lời

4

Vì API hiện tại, bạn không thể thoát khỏi nó.

groupingBy

là một hoạt động thiết bị đầu cuối (nó không trả lại một Stream), do đó hoạt động sẽ kết thúc dòng.

Tùy thuộc vào những gì bạn muốn làm sau này trong thao tác bản đồ cuối cùng, bạn có thể tạo bộ sưu tập tùy chỉnh sẽ "ở lại" bên trong luồng; ngay cả khi bên trong bạn có lẽ vẫn sẽ thu thập các yếu tố vào một Bản đồ.

+0

Có bất kỳ hoạt động thu nào không phải là thiết bị đầu cuối? Nếu không, tôi cho rằng điều này là do thiết kế, vì vậy nó sẽ là tốt hơn để tự mở một dòng mới, tôi có phải không? –

+1

@ lukegv nope không có; bạn đúng rồi. – Eugene

5

Bạn có thể làm bất cứ điều gì bạn thích trong bộ thu hạ lưu, miễn là bạn có thể mô tả hoạt động dưới dạng Collector. Hiện tại, chỉ tương đương với hoạt động trung gian map, bộ thu mapping, nhưng Java 9 cũng sẽ thêm filteringflatMapping (bạn cũng có thể tự thực hiện trong Java 8) và đã tương đương với hầu hết mọi hoạt động đầu cuối.

Tất nhiên, một thiết bị lồng nhau của các nhà sưu tập sẽ trông hoàn toàn khác biệt so với một chuỗi các hoạt động Suối làm như vậy ...

Tuy nhiên, nếu bạn muốn để xử lý nhóm hoàn thành, không có cách nào xung quanh hoàn thành bộ sưu tập grouping Đầu tiên. Đây không phải là giới hạn của API, nhưng nội tại đối với hoạt động nhóm hoặc bất kỳ hoạt động nào nói chung, nếu bạn muốn xử lý một kết quả hoàn chỉnh, trước tiên bạn sẽ cần phải hoàn tất thao tác. Bất kể API trông như thế nào, ví dụ: bạn có thể ẩn hoạt động tiếp theo trong trình thu thập theo cách thức collectingAndThen, tạo và điền vào Map là không thể tránh khỏi vì bản đồ đang thực hiện việc duy trì các nhóm.Các nhóm được xác định bằng các khóa và logic tra cứu của Map, vì vậy, ví dụ: sử dụng một SortedMap với bộ so sánh tùy chỉnh hoặc IdentityHashMap, có thể thay đổi hoàn toàn logic nhóm.