2015-02-18 27 views
5

Tôi hiện đang có các tình huống sau đây:Sum thuộc tính của đối tượng với Suối API

Tôi đã có một đối tượng Report mà có thể chứa nhiều Query đối tượng. Các đối tượng Query có các thuộc tính: Optional<Filter> comparisonFilter, Optional<String> filterChoiceint queryOutput.

Không phải mọi truy vấn đều có bộ lọc so sánh, vì vậy trước tiên tôi kiểm tra điều đó. Sau đó, tôi chắc chắn rằng tôi nhận được các truy vấn cho một bộ lọc cụ thể (mà không phải là vấn đề ở đây, vì vậy tôi sẽ không thảo luận chi tiết này). Mỗi bộ lọc có một số lựa chọn, trong đó số lượng các lựa chọn là biến.

Dưới đây là một ví dụ về đầu vào (những Query đối tượng đều có comparisonFilter giống nhau):

Query 1 -- Choice: 'First' -- Output: 10 
Query 1 -- Choice: 'First' -- Output: 5 
Query 1 -- Choice: 'Second' -- Output: 25 
Query 1 -- Choice: 'Third' -- Output: 10 

Bây giờ, tôi muốn tổng hợp các kết quả đầu ra truy vấn cho mọi sự lựa chọn độc đáo. Tôi hiện đang có mã này:

report 
.getQueries() 
.stream() 
.filter(q -> q.getComparisonFilter().isPresent()) 
.filter(q -> q.getComparisonFilter().get().equals(view.getFilter().get())) 
.forEach(query -> { 

    //Sum the query outputs per choice 

}); 

tôi có thể làm điều này bằng cách tạo ra một Map<String, Integer>, nơi chính là sự lựa chọn và giá trị là đầu vào truy vấn. Nhưng sau đó tôi sẽ cần phải lặp lại thông qua các Map một lần nữa để sử dụng giá trị cho một cái gì đó (mà không quan trọng ở đây).

Đầu ra phải được như thế này:

Choice: 'First' -- Summed Output: 15 
Choice: 'Second' -- Summed Output: 25 
Choice: 'Third' -- Summed Output: 10 

Nhưng tôi muốn sử dụng này 'Output tóm gọn' trực tiếp trong một forEach trên dòng, nhưng nếu điều này là không thể thực hiện hoặc thực tế nữa, tôi không sao với.

Tôi muốn thực hiện điều này theo cách 'Java 8', nhưng dường như tôi không thể tìm hiểu cách thực hiện.

Vì vậy, câu hỏi của tôi là: Có thể làm điều này ngắn hơn với API luồng mới không?

Lưu ý: Nếu có ai đó có ý tưởng về cách tôi có thể làm cho câu hỏi này tổng quát hơn (có thể là tiêu đề tốt hơn và một số khái quát), vui lòng cho tôi biết!

+1

Nghe có vẻ như nếu bạn có vấn đề này: http: //www.leveluplunch.com/java/examples/java-util-stream-groupingBy-example/ –

+0

Cảm ơn nhận xét của bạn @LutzHorn, đây là một liên kết rất hữu ích. Tôi nhận được phương thức 'groupingBy', và sau đó tôi có thể stream' keySet', nhưng sau đó nó có thể tổng hợp 'queryInput' cho mọi lựa chọn từ bên trong luồng không? Có lẽ một số giảm là có thể? – bashoogzaad

+2

@bashoogzaad Tôi không chắc chắn tôi có được những gì bạn muốn làm; đặc biệt là việc sử dụng 'Tùy chọn filterChoice'. Bạn có muốn tổng hợp các truy vấn từ giá trị trong tùy chọn này hoặc từ các giá trị trong tùy chọn có chứa Bộ lọc không? Có thể có một ví dụ về đầu vào/đầu ra không? –

Trả lời

5

Nếu tôi hiểu rõ, bạn thực sự đang tìm kiếm một số groupingBy và sau đó bạn phải nhóm các giá trị bằng cách cộng tổng số thuộc tính int của chúng.

Các groupingBy sẽ cung cấp cho bạn một Map<String, List<Query>> nhưng sau đó các nhà sưu tập ở hạ nguồn (Collectors.summingInt trong trường hợp này) sẽ tổng hợp tất cả các giá trị của các intQuery trường hợp trong danh sách, kết quả trong một Map<String, Integer>.

import static java.util.stream.Collectors.groupingBy; 
import static java.util.stream.Collectors.summingInt; 
... 

Map<String, Integer> map = 
    report.getQueries() 
      .stream() 
      .filter(q -> q.getComparisonFilter().isPresent()) 
      .filter(q -> q.getComparisonFilter().get().equals(view.getFilter().get())) 
      .collect(groupingBy(q -> q.filterChoice.get(), summingInt(q -> q.queryOutput))); 

Lưu ý rằng bạn nên kiểm tra xem filterChoice bắt buộc là không có sản phẩm nào (có thể thêm một mệnh đề khác filter?). Bạn có thể thấy số gist nhỏ này cho bản trình diễn cơ bản và đơn giản để minh họa nguyên tắc.

Cũng lớp Optional cung cấp một thực hiện hợp lý của equals nên mệnh đề bộ lọc có thể trông như thế này:

.filter(q -> q.getComparisonFilter().equals(view.getFilter())) 
+2

Tôi sắp sửa trả lời tương tự. Chỉ cần 20 giây phía sau bạn ... –

+0

Cảm ơn bạn đã trả lời tuyệt vời! Dường như nó hoạt động trong ý chính, nhưng tôi nhận được một lỗi rằng 'Map ' không thể được đưa vào 'Map '. Tôi nghĩ rằng nó có cái gì để làm với mã của tôi, nhưng filterChoice chỉ là một 'Tùy chọn '. Tôi sẽ cố gắng tìm ra điều này và chấp nhận câu trả lời của bạn. – bashoogzaad

+2

@bashoogzaad Bạn có biên dịch với Eclipse hay Javac không? Trình biên dịch Eclipse vẫn còn một số vấn đề với suy luận kiểu (và với một số tính năng Java 8 nói chung). Hãy thử biên dịch nó với javac. Nếu nó không biên dịch; hoặc bạn đã thực hiện một lỗi hoặc bạn sẽ phải giúp trình biên dịch bằng cách cung cấp các loại ;-) –

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