如何使用流来展平和分组此HashMap?

时间:2019-03-08 01:42:58

标签: java java-8 java-stream

考虑到字母到数字的映射,我想返回一个字符串列表,其中每个字符串都是一个用逗号分隔的字母列表,这些字母按字母的关联数字分组。

对于此地图

    Map<String, Integer> map = new HashMap<String, Integer>();
    map.put("A", 1);
    map.put("B", 2);
    map.put("C", 4);
    map.put("D", 1);
    map.put("E", 1);
    map.put("F", 2);

我想返回一个包含以下内容的列表:

"A,D,E" "B,F", "C"

有什么建议可以使用1.8流功能实现吗?

3 个答案:

答案 0 :(得分:5)

这种方式在最初流式传输后不引用map,并最大限度地利用了流式传输功能:

return map.entrySet().stream()
    .collect(Collectors.groupingBy(
        Map.Entry::getValue,
        Collectors.mapping(Map.Entry::getKey, Collectors.joining(","))))
    .values().stream().collect(Collectors.toList());

或更简洁,但使用流较少(感谢@Kartik):

return new ArrayList<>(map.entrySet().stream()
    .collect(Collectors.groupingBy(
        Map.Entry::getValue,
        Collectors.mapping(Map.Entry::getKey, Collectors.joining(","))))
    .values());

在这两种方法中,如果您将TreeMap::new作为自变量添加到Collectors.groupingBy的两个现有参数之间,则会对“内部”部分进行排序。

答案 1 :(得分:2)

您可以先按值对条目进行分组,然后使用Collectors.joining(",")

List<String> result = map.entrySet().stream()
        .collect(Collectors.groupingBy(Map.Entry::getValue))
        .values().stream()
        .map(e -> e.stream()
                .map(Map.Entry::getKey)
                .collect(Collectors.joining(",")))
        .collect(Collectors.toList());

答案 2 :(得分:0)

这是我的尝试

List<String> results = map
    .entrySet()
    .stream()
    .collect(
        Collectors.groupingBy(
            Map.Entry::getValue,
            Collectors.mapping(
                Map.Entry::getKey,
                Collectors.toList())))
    .values()
    .stream()
    .map(letters -> String.join(",", letters))
    .collect(Collectors.toList());