2015-02-03 63 views
5

Tôi có Bản đồ Danh sách của một đối tượng cụ thể và tôi muốn thêm tất cả các phần tử của danh sách dựa trên biến mẫu cụ thể.Java 8 - Cách tổng hợp tất cả phần tử Danh sách trong Bản đồ Danh sách

Object của tôi:

class Risk{ 
    Integer id, riskValue, totRisk=0; 
    String name; 

    Integer getId(){ 
     return id; 
    } 
    Risk(Object[] result){ 
     id=(Integer)result[0]; 
     riskValue=(Integer)result[1]; 
     name=(String)result[3]; 
    } 
} 

tôi nhận được từ cơ sở dữ liệu một Danh sách Mảng kiểu đối tượng:

List<Object[]> results=getResults(); 

tôi sử dụng Java 8 vào nhóm dữ liệu của tôi bằng ID, bởi vì tôi muốn SUM by riskValue tất cả các đối tượng thuộc loại Risk có cùng số id.

Đây là những gì tôi làm:

List<Risk> risks=results.stream().map(Risk::new).collect(Collectors.toList()); 
Map<Integer, List<Risk>> byId=risks.stream.collect(Collectors.groupingBy(Risk::getId)); 

Tại thời điểm này, tôi có tất cả các đối tượng rủi ro của tôi được phân nhóm theo ID. Và tôi muốn cho mỗi danh sách để tổng hợp tất cả các đối tượng bằng cách riskValue và có tổng trong biến totRisk

Làm thế nào để tính toán trong biến totRisk tổng của các biến riskValue trong mỗi mục sách?

Note1: Tôi muốn làm điều đó bằng cách sử dụng Java 8, tôi biết cách sử dụng Java 7 trở xuống.

Lưu ý2: Có lẽ bạn cũng có thể thực hiện việc này một lần bằng cách không phải là nhóm đầu tiên theo ID. Những gì tôi muốn đạt được là tổng hợp tất cả các đối tượng với cùng một ID trong bản gốc List<Object[]> results. Nếu nó có thể được thực hiện với chỉ một tuyên bố thậm chí còn tốt hơn.

Trả lời

7

Bạn phải lưu ý rằng bạn có thể kết hợp Collector s. Xem Collectors.groupingBy(Function,Collector)

Map<Integer, Integer> byId=risks.stream.collect(
    Collectors.groupingBy(Risk::getId, Collectors.summingInt(Risk::getRiskValue))); 

Bạn cũng có thể kết hợp nó với những hoạt động đầu tiên:

Map<Integer, Integer> byId=results.stream().map(Risk::new).collect(
    Collectors.groupingBy(Risk::getId, Collectors.summingInt(Risk::getRiskValue))); 

Lưu ý rằng tôi giả sử rằng bạn có một phương pháp getRiskValue() trong lớp học của bạn Risk, nếu không bạn phải thay thế Risk::getRiskValue với một lambda biểu hiện r -> r.riskValue để truy cập trường, tuy nhiên, có phương pháp getter luôn được khuyến nghị.

Bản đồ kết quả từ tổng số thành id.


Sau khi đọc câu hỏi của bạn một lần nữa, tôi nhận thấy rằng bạn thực sự muốn tổng hợp riskValue và lưu trữ nó trong totRisk của mỗi trường hợp (?) Risk. Đây là một chút phức tạp hơn vì nó không phù hợp với những mô hình phổ biến sử dụng:

Map<Integer, List<Risk>> byId=results.stream().map(Risk::new).collect(
    Collectors.groupingBy(Risk::getId, Collectors.collectingAndThen(
    Collectors.toList(), l-> { 
     int total=l.stream().collect(Collectors.summingInt(r -> r.riskValue)); 
     l.forEach(r->r.totRisk=total); 
     return l; 
    }))); 

vào thời điểm này, chúng tôi thực sự cần chuyển sang sử dụng import static java.util.stream.Collectors.*;:

Map<Integer, List<Risk>> byId=results.stream().map(Risk::new).collect(
    groupingBy(Risk::getId, collectingAndThen(toList(), l-> { 
    int total=l.stream().collect(summingInt(r -> r.riskValue)); 
    l.forEach(r->r.totRisk=total); 
    return l; 
    }))); 
+0

Chỉ cần chắc chắn: Bản đồ đó là Bản đồ của "id": "total" cho id đó, đúng không? – horus

+1

Bạn nói đúng, nó ánh xạ tới 'total' – Holger

+0

điều cuối cùng: sử dụng biểu thức lambda như bạn đã viết ở trên bằng cách thay thế ** Risk :: getTotRisk ** with ** r -> r.totRisk ** không hoạt động với tôi (nó không biên dịch). Có thể đạt được nó với một lamba mà không cần phải tạo ra getter? – horus

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