卡在Java8 Lambda表达式上了

6

我有一个Map<Integer,Doctor> docLib=new HashMap<>();用来保存Doctor类。

Doctor类有getSpecialization()方法可以返回一个String类型的值,
getPatients()方法可以返回一个类为Person的集合。

在主方法中,我输入:

public Map<String,Set<Person>> getPatientsPerSpecialization(){
    Map<String,Set<Person>> res=this.docLib.entrySet().stream().
                         map(d->d.getValue()).
                         collect(groupingBy(d->d.getSpecialization(),
                                            d.getPatients()) //error
                                 );
   return res;
}

如您所见,我在使用groupingBy方法时遇到了问题。我尝试将相同的值d发送给该方法,但结果是错误的。如何解决这个问题?


看起来你得到了一些很好的答案,但是在将来,请包括你收到的确切错误消息以及任何与你预期行为不同的行为描述。只说“它是错的”并不能说明你的问题。 - skrrgwasme
2个回答

5
你需要一个第二个收集器来实现映射
public Map<String,Set<Person>> getPatientsPerSpecialization(){
    return this.docLib
               .values()
               .stream()
               .collect(Colectors.groupingBy(Doctor::getSpecialization,
                                             Collectors.mapping(Doctor::getPatients,toSet()))
                       );
}

编辑:

我认为我的原始答案可能是错误的(没有测试很难说)。由于Doctor::getPatients返回一个Collection,我认为我的代码可能会返回一个Map<String,Set<Collection<Person>>>而不是所需的Map<String,Set<Person>>

最简单的方法是再次迭代该Map以产生所需的Map

public Map<String,Set<Person>> getPatientsPerSpecialization(){
    return this.docLib
               .values()
               .stream()
               .collect(Colectors.groupingBy(Doctor::getSpecialization,
                                             Collectors.mapping(Doctor::getPatients,toSet()))
                       )
               .entrySet()
               .stream()
               .collect (Collectors.toMap (e -> e.getKey(),
                                           e -> e.getValue().stream().flatMap(c -> c.stream()).collect(Collectors.toSet()))
                        );
}

也许有一种方法可以通过单个流管道获得相同的结果,但我现在看不到它。

2
你可以使用docLib.values().stream()代替docLib.entrySet().stream().map(d->d.getValue()) - Jesper
@Holger 很酷 :). 我在想我是否错过了在Java 8中进行此扁平映射的某种方法。我猜我没有。 - Eran

2

你可以使用toMap代替groupingBy

public Map<String, Set<Person>> getPatientsPerSpecialization() {
    return docLib.values()
                 .stream()
                 .collect(toMap(Doctor::getSpecialization,
                                d -> new HashSet<>(d.getPatients()),
                                (p1, p2) -> Stream.concat(p1.stream(), p2.stream()).collect(toSet())));
}

它的作用是将医生按专业分组,并映射到它所拥有的一组患者(因此是一个Map>)。
如果在从管道收集数据时遇到已存储为该映射键的专业医生,则使用合并函数生成一个新的值集合,其中包含两个集合(已存储为键值的集合和要与键相关联的集合)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接