在Java 8中如何在流中重复键时收集到Map中以形成值列表

时间:2018-09-03 04:19:48

标签: java java-8 hashmap java-stream

我有一个二维数组或EntrySet形式的元素流。我需要将这些收集在Map中。现在的问题是元素流可以有重复的元素。假设我希望该值是一个列表:

Map<String,List<String>>

示例:

class MapUtils
{
// Function to get Stream of String[]
private static Stream<String[]> getMapStream()
{
    return Stream.of(new String[][] {
            {"CAR", "Audi"},
            {"BIKE", "Harley Davidson"},
            {"BIKE", "Pulsar"}
    });
}

// Program to convert Stream to Map in Java 8
public static void main(String args[])
{
    // get stream of String[]
    Stream<String[]> stream = getMapStream();

    // construct a new map from the stream
    Map<String, String> vehicle =
            stream.collect(Collectors.toMap(e -> e[0], e -> e[1]));

    System.out.println(vehicle);
}
}

输出:

java.lang.IllegalStateException: Duplicate key Harley Davidson

我想办法

  1. 我可以在e->e[0]e->e[1]上进行操作以解决问题。那可能吗?为此,我需要访问正在收集的当前地图对象。我不确定这是否有意义。
  2. 使用Java 8流可以实现这一目标的方法。

预期输出:

{CAR=[Audi], BIKE=[Harley Davidson, Pulsar]}

2 个答案:

答案 0 :(得分:5)

这就是groupingBy的作用:

Map<String,List<String>> vehicle = 
    stream.collect(Collectors.groupingBy(e -> e[0], 
                   Collectors.mapping(e -> e[1],
                                      Collectors.toList())));

输出图:

{CAR=[Audi], BIKE=[Harley Davidson, Pulsar]}

答案 1 :(得分:2)

您可以使用groupingBy

getMapStream()
      .map(item -> Arrays.asList(item))
      .collect(Collectors.groupingBy(l->l.get(0),
           Collectors.mapping(l1->l1.get(1),Collectors.toList())));

或将toMap()与合并功能一起使用。

     Map<String,List<String>> vehicle = getMapStream()
            .collect(Collectors.toMap(item->item[0],
       item->new ArrayList<>(Arrays.asList(item[1])),
                            (l1,l2)->{l1.addAll(l2);return l1;}));