Java 8方式将集合转换为一个键多个值映射

时间:2016-02-28 10:26:08

标签: java dictionary collections java-8

使用Java 8执行以下代码的任何方法。

        final Map<String, Collection<ProductStrAttributeOverrideRulesModel>> attributeRulesMap = new HashMap<String, Collection<ProductStrAttributeOverrideRulesModel>>();
        for (final ProductStrAttributeOverrideRulesModel rule : rules)
        {
            final String key = rule.getProductStrAttributeOverride().getProductStrTypeField().getAttributeDescriptorQualifier();
            if (attributeRulesMap.containsKey(key))
            {
                final Collection<ProductStrAttributeOverrideRulesModel> currentRules = attributeRulesMap.get(key);
                currentRules.add(rule);
            }
            else
            {
                final Collection<ProductStrAttributeOverrideRulesModel> list = new LinkedList<ProductStrAttributeOverrideRulesModel>();
                list.add(rule);
                attributeRulesMap.put(key, list);
            }
        }

如果它只是

 final Map<String, ProductStrAttributeOverrideRulesModel> attributeRulesMap

比我可以做的如下,但我需要根据键将整个集合排列在地图中,每个键可以在集合中存储多个值。

Map<String, ProductStrAttributeOverrideRulesModel> result =
choices.stream().collect(Collectors.toMap(ProductStrAttributeOverrideRulesModel::getProductStrAttributeOverride.getProductStrTypeField.getAttributeDescriptorQualifier,
                                          Function.identity()));

2 个答案:

答案 0 :(得分:3)

您可以使用groupingBy

Map<String,List<ProductStrAttributeOverrideRulesModel>>
    map = 
        choices.stream()
               .collect(Collectors.groupingBy(rule -> rule.getProductStrAttributeOverride().getProductStrTypeField().getAttributeDescriptorQualifier()));

如果您不想要List,则可以将第二个参数传递给groupingBy并指定您想要的Collection。例如:

Map<String,Collection<ProductStrAttributeOverrideRulesModel>>
    map =
        choices.stream()
               .collect(Collectors.groupingBy(rule -> rule.getProductStrAttributeOverride().getProductStrTypeField().getAttributeDescriptorQualifier(),
                                              Collectors.toCollection(HashSet::new)));

答案 1 :(得分:1)

请注意,它并不总是必须是Stream操作。您的代码也将受益于使用“菱形运算符”(虽然不是Java 8的新功能)和使用新的集合运算,即computeIfAbsent,它允许忽略循环内的整个条件及其代码重复。把它们放在一起,你会得到:

final Map<String, Collection<ProductStrAttributeOverrideRulesModel>>
                                                   attributeRulesMap = new HashMap<>();
for(final ProductStrAttributeOverrideRulesModel rule: rules)
{
    final String key = rule.getProductStrAttributeOverride()
        .getProductStrTypeField().getAttributeDescriptorQualifier();
    attributeRulesMap.computeIfAbsent(key, x->new LinkedList<>()).add(rule);
}

如果您愿意,也可以通过forEach调用替换循环:

rules.forEach(rule -> attributeRulesMap.computeIfAbsent(
    rule.getProductStrAttributeOverride()
        .getProductStrTypeField().getAttributeDescriptorQualifier(),
    x->new LinkedList<>()).add(rule)
);

虽然这是否比这里的经典循环有所改进值得商榷......