我的课有两个领域:
MyKey
-我要分组的密钥Set<MyEnum>
-我要展平和合并的集合。我有一个这样的对象的列表,我想要的是Map<MyKey, Set<MyEnum>
使用此键从对象的所有myEnums中获得其值所连接的对象。
例如,如果我有三个对象:
myKey: key1, myEnums: [E1]
myKey: key1, myEnums: [E2]
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;
})));
它有两个问题:
该HashSet
还原里面似乎所有的键之间共享。就是说上述示例的实际运行结果是key1 => [E1, E2, E3], key2 => [E1, E2, E3]
。为什么会这样呢?
即使这段代码有效,但在减少部分内容(我必须手动处理构造人工集合的逻辑)方面看起来尤其难看。有更好的方法吗?
谢谢!
请注意,您只会创建一个标识对象:new HashSet<MyEnum>()
。
在BinaryOperator
您提供的第三个参数必须是幂等的,以同样的方式共同数学运算符是,如x = y + z
不改变的价值y
和z
。
这意味着您需要合并两个输入集a
和b
,而无需更新任何一个。
另外,使用枚举时,应使用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] 删除。
我来说两句