MGh*_*oft 5 java java-8 collectors
我的班有两个领域:
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;
})));
Run Code Online (Sandbox Code Playgroud)
它有两个问题:
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;
})));
Run Code Online (Sandbox Code Playgroud)
UPDATE
更短,更简化的版本,在累积结果时不必继续创建新集:
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; }
)));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1460 次 |
| 最近记录: |