Java 8:按字段对集合进行分组,然后使用流将集合展平并作为映射值加入集合?

MGhostSoft

我的课有两个领域:

  • MyKey -我要分组的密钥
  • Set<MyEnum> -我要展平和合并的集合。

我有一个这样的对象的列表,我想要的是Map<MyKey, Set<MyEnum>使用此键从对象的所有myEnums中获得其值所连接的对象。

例如,如果我有三个对象:

  1. myKey: key1, myEnums: [E1]
  2. myKey: key1, myEnums: [E2]
  3. myKey: key2, myEnums: [E1, E3]

预期结果应为:

key1 => [E1, E2], key2 => [E1, E3]

我想出了以下代码:

Map<MyKey, Set<MyEnum>> map = myObjs.stream()
        .collect(Collectors.groupingBy(
                MyType::getMyKey,
                Collectors.reducing(
                        new HashSet<MyEnum>(),
                        MyType::getMyEnums,
                        (a, b) -> {
                            a.addAll(b);
                            return a;
                        })));

它有两个问题:

  1. HashSet还原里面似乎所有的键之间共享。就是说上述示例的实际运行结果是key1 => [E1, E2, E3], key2 => [E1, E2, E3]为什么会这样呢?

  2. 即使这段代码有效,但在减少部分内容(我必须手动处理构造人工集合的逻辑)方面看起来尤其难看。有更好的方法吗?

谢谢!

安德烈亚斯

请注意,您只会创建一个标识对象:new HashSet<MyEnum>()

BinaryOperator您提供的第三个参数必须是幂等的,以同样的方式共同数学运算符是,如x = y + z不改变的价值yz

这意味着您需要合并两个输入集ab,而无需更新任何一个。

另外,使用枚举时,应使用EnumSet,而不是HashSet

Map<MyKey, Set<MyEnum>> map = myObjs.stream()
        .collect(Collectors.groupingBy(
                    MyType::getMyKey,
                    Collectors.reducing(
                        EnumSet.noneOf(MyEnum.class), // <-- EnumSet
                        MyType::getMyEnums,
                        (a, b) -> {
                            EnumSet<MyEnum> c = EnumSet.copyOf(a); // <-- copy
                            c.addAll(b);
                            return c;
                        })));

更新

更短,更简化的版本,在累积结果的同时不必继续创建新的集合:

Map<MyKey, Set<MyEnum>> map = myObjs.stream()
        .collect(Collectors.groupingBy(
                    MyType::getMyKey,
                    Collector.of(
                            () -> EnumSet.noneOf(MyEnum.class),
                            (r, myObj) -> r.addAll(myObj.getMyEnums()),
                            (r1, r2) -> { r1.addAll(r2); return r1; }
                    )));

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章