如何将二维数组收集到 Map<String, Set<String>> 中?

How can I collect two-dimensional Array into a Map<String, Set<String>>?

我有一个由两个字符串组成的数组。

var array = new String[][]{
    {"a", "1"},
    {"a", "2"},
    {"b", "3"},
    ...
};

如何将上面的数组收集成一个Map<String, Set<String>>,其键是每个数组的第一个元素,值是数组第二个元素的集合?

这样我就能得到以下地图?

// Map<String, Set<String>>
<"a", ["1, "2"]>,
<"b", ["3"]>,
...

到目前为止,我发现我可以像这样对每个数组的第一个元素进行分类。


Arrays.stream(array).collect(Collectors.groupingBy(
        a -> ((String[])a)[0],
        // how can I collect the downstream?
);

你可以遍历你的数组,对于每个字符你都可以检查这个键之前是否保存在你的地图中,如果是,只需将相应的字符推到重复键的列表中

您可以使用 for-each 循环

简单地做到这一点
   Map<String, Set<String>> map=new HashMap<>();
   for(String []arr : array){
     Set<String> set = map.getOrDefault(arr[0], new HashSet<>());
     set.add(arr[1]);
     map.put(arr[0],set);
   }
   System.out.println(map);
 

输出:

{a=[1, 2], b=[3]}

你需要一个Collectors.mapping(也不需要在里面指定String[]

var array = new String[][]{{"a", "1"}, {"a", "2"}, {"b", "3"},};

Map<String, Set<String>> res = Arrays.stream(array).collect(Collectors.groupingBy(
        a -> a[0],
        Collectors.mapping(a -> a[1], Collectors.toSet())
));

System.out.println(res); // {a=[1, 2], b=[3]}

您可以将 Collectors.mapping()toSet() 下游一起使用:

Collectors.groupingBy(a -> a[0],
    Collectors.mapping(v -> v[1], Collectors.toSet()))

产生 {a=[1, 2], b=[3]}。首先将流元素映射到数组的第二个元素,然后将它们收集为映射到组键的集合。

结合使用 Collectors.groupingByCollectors.mapping()

public static void main(String[] args) {
    var array = new String[][]{
        {"a", "1"},
        {"a", "2"},
        {"b", "3"}
    };

    Map<String, Set<String>> result =
        Stream.of(array)
            .collect(Collectors.groupingBy(arr -> arr[0],
                Collectors.mapping(arr -> arr[1],
                    Collectors.toSet())));

    System.out.println(result);
}

另一种方法是利用 Collector.of():

Map<String, Set<String>> result =
    Stream.of(array)
        .collect(Collector.of(
            HashMap::new,
            (Map<String, Set<String>> map, String[] arr) ->
                map.computeIfAbsent(arr[0], k -> new HashSet<>()).add(arr[1]),
            (Map<String, Set<String>> left, Map<String, Set<String>> right) ->
                { left.putAll(right); return left; }));

输出

{a=[1, 2], b=[3]}

而不是 Collectors.groupingBy,您可以使用 Collectors.toMap

public class Main {

  public static void main(String[] args) throws Exception {
    String[][] array = new String[][]{{"a", "1"}, {"a", "2"}, {"b", "3"}};
    Map<String, Set<String>> map = Arrays.stream(array).collect(Collectors.toMap(
            arr -> arr[0],
            arr -> new HashSet<>(Collections.singleton(arr[1])),
            (l, r) -> {
              l.addAll(r);
              return l;
            }));
    System.out.println(map);
  }
}

第一个参数是keyMapper,第二个是valueMapper,第三个- mergeFunction