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. 即使这段代码有效,但在减少部分内容(我必须手动处理构造连接集合的逻辑)方面看起来尤其难看。有更好的方法吗?

谢谢!

安德烈亚斯(Andreas)

请注意,您只会创建一个标识对象: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条评论
登录后参与评论

相关文章

来自分类Dev

Java的原始8流集合映射方法

来自分类Dev

使用java8流构建集合

来自分类Dev

Java 8流与集合存储

来自分类Dev

对对象列表进行分组并使用Java集合进行计数

来自分类Dev

如何使用集合按Java中的对象分组?

来自分类Dev

如何使用集合按Java中的对象分组?

来自分类Dev

在Java8中使用Stream groupingby按字符串集合对分组

来自分类Dev

在Java中按属性映射对象的集合

来自分类Dev

使用Java 8流对集合进行排序将其转换为Map

来自分类Dev

java 8流从类型A的集合创建类型B的集合

来自分类Dev

如何将嵌套的Java集合中的所有项目展平为单个List?

来自分类Dev

Java MapStruct 集合映射

来自分类Dev

使用Java8流实现此集合的最佳方法

来自分类Dev

处理嵌套集合与Java 8流

来自分类Dev

集团通过使用Java流集合属性

来自分类Dev

使用Java 8 Streams API对集合进行“包含”类型的查询

来自分类Dev

Java 8 Streams修改集合值

来自分类常见问题

Java 8 Streams可以对集合中的项目进行操作,然后将其删除吗?

来自分类Dev

Java集合

来自分类Dev

Java集合

来自分类Dev

在Java 8中递归展平嵌套映射的值

来自分类Dev

Java 8给定键的有序集合,按键对映射进行排序

来自分类Dev

使用Java Stream迭代集合的集合?

来自分类Dev

Java 8流:替换流集合中的单个项目

来自分类Dev

执行流操作Java 8时更新集合

来自分类Dev

修改后的集合中的Java 8流

来自分类Dev

Java 8流结合了两个不同的集合

来自分类Dev

Java的8流 - 合并地图集合

来自分类Dev

Java 8-具有不同集合的流嵌套ForEach