M4V*_*V3N 20 java lambda java-8 java-stream
我想转换我看起来像这样的地图:
{
key="someKey1", value=Apple(id="1", color="green"),
key="someKey2", value=Apple(id="2", color="red"),
key="someKey3", value=Apple(id="3", color="green"),
key="someKey4", value=Apple(id="4", color="red"),
}
Run Code Online (Sandbox Code Playgroud)
到另一个地图,将所有相同颜色的苹果放入同一个列表中:
{
key="red", value=list={apple1, apple3},
key="green", value=list={apple2, apple4},
}
Run Code Online (Sandbox Code Playgroud)
我尝试了以下方法:
Map<String, Set<Apple>> sortedApples = appleMap.entrySet()
.stream()
.collect(Collectors.toMap(l -> l.getColour, ???));
Run Code Online (Sandbox Code Playgroud)
我是在正确的轨道上吗?我应该使用过滤器来执行此任务吗?有没有更简单的方法?
Era*_*ran 14
Collectors.groupingBy比Collectors.toMap这个任务更合适(尽管两者都可以使用).
Map<String, List<Apple>> sortedApples =
appleMap.values()
.stream()
.collect(Collectors.groupingBy(Apple::getColour));
Run Code Online (Sandbox Code Playgroud)
或者,将它们分组Set使用:
Map<String, Set<Apple>> sortedApples =
appleMap.values()
.stream()
.collect(Collectors.groupingBy(Apple::getColour,
Collectors.mapping(Function.identity(),
Collectors.toSet())));
Run Code Online (Sandbox Code Playgroud)
或(如Aomine评论):
Map<String, Set<Apple>> sortedApples =
appleMap.values()
.stream()
.collect(Collectors.groupingBy(Apple::getColour, Collectors.toSet()));
Run Code Online (Sandbox Code Playgroud)
Ous*_* D. 11
如果你想继续,toMap你可以得到如下结果:
map.values() // get the apples
.stream() // Stream<Apple>
.collect(toMap(Apple::getColour, // group by colour
v -> new HashSet<>(singleton(v)), // have values as set of apples
(l, r) -> {l.addAll(r); return l;})); // merge colliding apples by colour
Run Code Online (Sandbox Code Playgroud)
values而不是entrySet因为我们不关心地图键.Apple::getColour是keyMapper用于提取我们希望分组的"东西" 的函数,在这种情况下是Apples颜色.v -> new HashSet<>(singleton(v))是valueMapper用于生成的映射值的函数(l, r) -> {l.addAll(r); return l;}合并函数用于HashSet在Apple颜色上存在键碰撞时组合两个.Map<String, Set<Apple>>但这是更好的groupingBy和toSet下游:
map.values().stream().collect(groupingBy(Apple::getColour, toSet()));
Run Code Online (Sandbox Code Playgroud)
流过地图values而不是entrySet因为我们不关心地图键.
Apple通过提供的分类函数对其进行分组Apple::getColour,然后在集合中收集值,从而toSet收集下游收集器.
最后,得到的地图是一个 Map<String, Set<Apple>>
简短,可读和惯用的方法.
您也可以在没有流的情况下执行此操作:
Map<String, Set<Apple>> res = new HashMap<>();
map.values().forEach(a -> res.computeIfAbsent(a.getColour(), e -> new HashSet<>()).add(a));
Run Code Online (Sandbox Code Playgroud)
values而不是entrySet因为我们不关心地图键.a.getColour()尚未与值关联,则尝试使用给定的映射函数计算其值e -> new HashSet<>()并将其输入到映射中.然后我们将其添加Apple到结果集中.a.getColour()已经与某个值computeIfAbsent相关联,则返回与之关联的现有值,然后我们调用add(a)它HashSet来进入Apple该集合.Map<String, Set<Apple>> 你可以使用Collectors.groupingBy和Collectors.toSet()
Map<String, Set<Apple>> sortedApples = appleMap.values() // Collection<Apple>
.stream() // Stream<Apple>
.collect(Collectors.groupingBy(Apple::getColour, // groupBy colour
Collectors.mapping(a -> a, Collectors.toSet()))); // collect to Set
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1122 次 |
| 最近记录: |