2016-01-11 20 views
11

Tôi có Map<A, Map<B, C>> và tôi muốn nhận được Map<B, List<C>> từ nó bằng cách sử dụng Luồng Java.Luồng Java: nhận các giá trị được nhóm theo khóa bản đồ bên trong

tôi cố gắng để làm điều đó như sau:

public <A, B, C> Map<B, List<C>> groupsByInnerKey(Map<A, Map<B, C>> input) { 
    return input.values() 
      .stream() 
      .flatMap(it -> it.entrySet().stream()) 
      .collect(Collectors.groupingBy(Map.Entry::getKey)); 
} 

Những gì tôi mong đợi:

  • flatMap đưa ra một Stream của Map.Entry<B, C>
  • collect(Collectors.groupingBy(...)) mất chức năng mà được áp dụng cho Map.Entry<B, C> và trả B, do đó, nó thu thập các giá trị của C vào List<C>.

Nhưng nó không biên dịch, nghĩa đen:

phương pháp

Non-tĩnh không thể được tham chiếu từ một bối cảnh tĩnh

tại Map.Entry::getKey trong dòng cuối cùng.

Ai đó có thể giải thích điều gì sai hoặc cách nào đúng để đạt được những gì tôi muốn?

+0

Có thể trùng lặp: http://stackoverflow.com/questions/29373026/how-to-get-all-values-from-the-inner-maps-of-a-map-using-a-common -key –

+0

@ShiladittyaChakraborty, không thực sự, tôi hỏi về lý do tại sao cách dự kiến ​​thực hiện điều này không hiệu quả. Ngoài ra, nhiệm vụ hơi khác so với câu hỏi bạn đã tham chiếu. – hotkey

Trả lời

11

luồng của mình gồm Map.Entry đối tượng nhưng muốn bạn muốn thu thập thực sự là giá trị của các mục nhập , không phải bản thân mục nhập. Với mã hiện tại của bạn, bạn sẽ nhận được Map<B, List<Map.Entry<B, C>>>.

Vì vậy, bạn chỉ đang thiếu một cuộc gọi đến Collectors.mapping. Nhà sưu tập này sẽ ánh xạ phần tử Luồng bằng hàm bản đồ đã cho và thu thập kết quả đó vào vùng chứa hạ lưu. Trong trường hợp này, người lập bản đồ là Map.Entry::getValue (do đó trả lại giá trị từ mục nhập bản đồ) và bộ thu hạ lưu thu thập thành List.

public <A, B, C> Map<B, List<C>> groupsByInnerKey(Map<A, Map<B, C>> input) { 
    return input.values() 
      .stream() 
      .flatMap(it -> it.entrySet().stream()) 
      .collect(Collectors.groupingBy(
       Map.Entry::getKey, 
       Collectors.mapping(Map.Entry::getValue, Collectors.toList()) 
      )); 
} 
+1

Cảm ơn, nó đã hoạt động. Vì vậy, tôi đã thực sự bối rối bởi thông báo lỗi của trình biên dịch. Nó nên nói về các loại không phù hợp, không phải về bối cảnh không tĩnh. :) – hotkey

7

Đường ống luồng của bạn trả lại Map<B, List<Map.Entry<B,C>>>, không phải là Map<B, List<C>>.

Để có được những gì một Map<B, List<C>>, bạn cần phải thêm một mapping rằng sẽ lập bản đồ Map.Entry<B,C>-C:

return input.entrySet() 
     .stream() 
     .flatMap(it -> it.getValue().entrySet().stream()) 
     .collect(Collectors.groupingBy(Map.Entry::getKey,Collectors.mapping(Map.Entry::getValue,Collectors.toList()))); 
Các vấn đề liên quan