想象一下,你有一个人名单,Roberts,Pauls,Richards等,这些是按姓名分组到Map<String, List<Person>>
的人。你想找到最老的保罗,罗伯特等......你可以这样做:
public static void main(String... args) {
List<Person> people = Arrays.asList(
new Person(23, "Paul"),
new Person(24, "Robert"),
new Person(32, "Paul"),
new Person(10, "Robert"),
new Person(4, "Richard"),
new Person(60, "Richard"),
new Person(9, "Robert"),
new Person(26, "Robert")
);
Person dummy = new Person(0, "");
var mapping = people.stream().collect(groupingBy(Person::getName, reducing(dummy, (p1, p2) -> p1.getAge() < p2.getAge() ? p2 : p1)));
mapping.entrySet().forEach(System.out::println);
}
说,我希望以[{1}}而不是Map<String, Integer>
的形式获得映射,我可以这样做:
Map<String, Person>
上述步骤为:
var mapping = people.stream().collect(groupingBy(Person::getName, mapping(Person::getAge, reducing(0, (p1, p2) -> p1 < p2 ? p2 : p1))));
Map<String/*Name*/, List<Person>>
映射到List<Person>
我想知道该怎么做:
List<Integer>
Map<String, List<Person>>
Map<String, Person>
转换为Map<String, Person>
。我想在分组链中做所有这些,减少和映射。这是&#34;伪代码&#34;:
Map<String, Integer>
我怎样才能做到这一点?
答案 0 :(得分:4)
使用3-argument version of toMap
collector:
people.stream().collect(toMap(
Person::getName,
Person::getAge,
Integer::max
));
答案 1 :(得分:3)
如果你真的想使用问题陈述中提到的groupingBy
,你仍然可以这样做:
final Map<String, Integer> oldestPersonByName = people.stream()
.collect(Collectors.groupingBy(Person::getName, Collectors.reducing(0, Person::getAge, Integer::max)));
对于减少,你必须传递一个标识元素,映射函数和用于减少的二元运算符,在这种情况下为max
。
答案 2 :(得分:2)
我认为它会像以下一样,也使用maxBy
代替reducing
。
people.stream().collect(
groupingBy(
Person::getName,
collectingAndThen(
maxBy(Comparator.comparing(Person::getAge)),
(Optional<Person> max) -> max.get().getAge()
)
)
);