Java 转换地图<;字符串,对象>;映射<;字符串,Set<;对象>&燃气轮机;带过滤器和流

Java 转换地图<;字符串,对象>;映射<;字符串,Set<;对象>&燃气轮机;带过滤器和流,java,lambda,java-8,java-stream,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"), } 到另一个将所有相同颜色的苹果放入相同列表

我想转换如下所示的地图:

{
  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"),
}
到另一个将所有相同颜色的苹果放入相同列表的地图:

{
  key="red", value=list={apple1, apple3},
  key="green", value=list={apple2, apple4},  
}
我尝试了以下方法:

Map<String, Set<Apple>> sortedApples = appleMap.entrySet()
    .stream()
    .collect(Collectors.toMap(l -> l.getColour, ???));
Map-sortedaples=appleMap.entrySet()
.stream()
.collect(收集器.toMap(l->l.getColor,?);

我走对了吗?我应该为此任务使用筛选器吗?有没有更简单的方法

收集器。groupingBy
收集器.toMap
更适合此任务(尽管两者都可以使用)

或者(正如Aomine所评论的):

Map sortedaples=
appleMap.values()
.stream()
.collect(Collectors.groupingBy(Apple::getcolor,Collectors.toSet());
您可以使用和
收集器.toSet()

Map-sortedaples=appleMap.values()//集合
.stream()//流
.collect(收集器.groupingBy(Apple::GetColor,//groupBy color
Collectors.mapping(a->a,Collectors.toSet());//集

如果要继续执行
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
  • 在map
    values
    上流,而不是
    entrySet
    ,因为我们不关心map键

  • 通过提供的分类功能(即,
    Apple::getcolor
    )对
    Apple
    进行分组,然后在一个集合中收集值,从而设置
    toSet
    下游收集器

  • 最后,生成的映射是
    映射

简短、易读且惯用的方法

您也可以在没有流的情况下执行此操作:

Map<String, Set<Apple>> res = new HashMap<>();
map.values().forEach(a -> res.computeIfAbsent(a.getColour(), e -> new HashSet<>()).add(a));
Map res=newhashmap();
map.values().forEach(a->res.computeifassent(a.getcolor(),e->newhashset()).add(a));
  • 迭代映射
    而不是
    入口集
    ,因为我们不关心映射键
  • 如果指定的键
    a.getColor()
    尚未与值关联,则尝试使用给定的映射函数
    e->new HashSet()
    计算其值,并将其输入映射。然后,我们将
    Apple
    添加到结果集
  • 如果指定的键
    a.getColor()
    已与值
    computeIfAbsent
    关联,则返回与之关联的现有值,然后我们调用
    HashSet
    上的
    add(a)
    Apple
    输入该集
  • 最后,生成的映射是
    映射

您已经问过如何使用流,但这里有另一种方法:

Map<String, Set<Apple>> result = new LinkedHashMap<>();
appleMap.values().forEach(apple -> 
    result.computeIfAbsent(apple.getColor(), k -> new LinkedHashSet<>()).add(apple));

Mapnice+1,最好迭代映射值,因为您没有使用
键执行任何操作,即
appleMap.values().forEach(apple->result.computeIfAbsent(apple.getcolor(),k->new LinkedHashSet()).add(apple))
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
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
map.values().stream().collect(groupingBy(Apple::getColour, toSet()));
Map<String, Set<Apple>> res = new HashMap<>();
map.values().forEach(a -> res.computeIfAbsent(a.getColour(), e -> new HashSet<>()).add(a));
Map<String, Set<Apple>> result = new LinkedHashMap<>();
appleMap.values().forEach(apple -> 
    result.computeIfAbsent(apple.getColor(), k -> new LinkedHashSet<>()).add(apple));