2016-10-05 30 views
7

Tôi muốn sử dụng Luồng Java để chạy qua Danh sách POJO, chẳng hạn như danh sách List<A> bên dưới và chuyển đổi nó thành Bản đồ Map<String, Set<String>>.Giá trị Java Stream Collectors.toMap là một Set

Ví dụ, lớp A là:

class A { 
    public String name; 
    public String property; 
} 

tôi đã viết mã bên dưới cho thu thập các giá trị thành một bản đồ Map<String, String>:

final List<A> as = new ArrayList<>(); 
// the list as is populated ... 

// works if there are no duplicates for name 
final Map<String, String> m = as.stream().collect(Collectors.toMap(x -> x.name, x -> x.property)); 

Tuy nhiên, vì có thể có nhiều POJO với cùng name, tôi muốn giá trị của bản đồ là Set. Tất cả property Chuỗi cho cùng một khóa name sẽ đi vào cùng một tập hợp.

Làm cách nào để thực hiện điều này?

// how do i create a stream such that all properties of the same name get into a set under the key name 
final Map<String, Set<String>> m = ??? 

Trả lời

15

groupingBy thực hiện chính xác những gì bạn muốn:

import static java.util.stream.Collectors.*; 
... 
as.stream().collect(groupingBy((x) -> x.name, mapping((x) -> x.property, toSet()))); 
+2

Chỉnh sửa nhỏ, tôi nghĩ rằng nó nên nhập tệp java.util.stream.Collectors tĩnh. *; – tkja

+1

Woops, sửa chữa: D – Nevay

+1

Bạn không cần dấu ngoặc đơn xung quanh một tham số lambda duy nhất. – shmosel

0

Ngoài ra, bạn có thể sử dụng tùy chọn chức năng sáp nhập của hàm Collectors.toMap Collectors.toMap (keyMapper, valueMapper, mergeFunction) như sau:

final Map<String, String> m = as.stream() 
           .collect(Collectors.toMap(
              x -> x.name, 
              x -> x.property, 
              (property1, property2) -> property1+";"+property2); 
+0

Câu hỏi là về việc thu thập các giá trị cho Đặt nhưng không phải là Chuỗi. – splatch

0

@Nevay 's câu trả lời chắc chắn là đúng cách để đi bằng cách sử dụng groupingBy, nhưng nó cũng có thể đạt được bằng cách toMap bằng cách thêm một mergeFunction như tham số thứ ba:

as.stream().collect(Collectors.toMap(x -> x.name, 
    x -> new HashSet<>(Arrays.asList(x.property)), 
    (x,y)->{x.addAll(y);return x;})); 

Mã này maps mảng đến một bản đồ với một chìa khóa như x.name và một giá trị như HashSet với một giá trị như x.property. Khi có khóa/giá trị trùng lặp, hàm sáp nhập tham số thứ ba sau đó được gọi để hợp nhất hai HashSet.

PS. Nếu bạn sử dụng thư viện chung Apache, bạn cũng có thể sử dụng số SetUtils::union của họ làm việc sáp nhập

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