Java 8 收集器.分组按映射值将收集结果设置为同一集

2022-09-02 20:06:12

对象在示例中使用来自包org.jsoup.nodes

import org.jsoup.nodes.Attribute;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

我需要按键对属性进行分组,并得到结果值。Set

Optional<Element> buttonOpt = ...;
Map<String, Set<String>> stringStringMap =
    buttonOpt.map(button -> button.attributes().asList().stream()
            .collect(groupingBy(Attribute::getKey, 
                  mapping(attribute -> attribute.getValue(), toSet()))))
            .orElse(new HashMap<>());

它似乎已正确收集,但值始终是单个字符串(由于库实现),其中包含按空格拆分的不同值。尝试改进解决方案:

Map<String, Set<HashSet<String>>> stringSetMap = buttonOpt.map(
        button -> button.attributes()
            .asList()
            .stream()
            .collect(groupingBy(Attribute::getKey, 
                        mapping(attribute -> 
                          new HashSet<String>(Arrays.asList(attribute.getValue()
                                                                .split(" "))),
                   toSet()))))
  .orElse(new HashMap<>());

结果我有不同的结构,但我需要Map<String, Set<HashSet<String>>>Map<String, Set<String>>

我已经检查了一些收集器,但尚未管理我的问题。

问题是:

如何合并与同一属性键相关的所有集合?


答案 1

您可以使用以下方式拆分属性并创建新条目进行分组:flatMap

Optional<Element> buttonOpt = ...
Map<String, Set<String>> stringStringMap =
        buttonOpt.map(button -> 
            button.attributes()
                  .asList()
                  .stream()
                  .flatMap(at -> Arrays.stream(at.getValue().split(" "))
                                       .map(v -> new SimpleEntry<>(at.getKey(),v)))
                  .collect(groupingBy(Map.Entry::getKey, 
                                      mapping(Map.Entry::getValue, toSet()))))
                .orElse(new HashMap<>());

答案 2

这是Java9的一种方式,

Map<String, Set<String>> stringSetMap = buttonOpt
    .map(button -> button.attributes().asList().stream()
        .collect(Collectors.groupingBy(Attribute::getKey, Collectors.flatMapping(
            attribute -> Arrays.stream(attribute.getValue().split(" ")), Collectors.toSet()))))
    .orElse(Collections.emptyMap());

推荐