【发布时间】:2018-05-29 23:47:25
【问题描述】:
假设您有一个人员列表,罗伯茨、保罗斯、理查兹等,这些人按名称分组到 Map<String, List<Person>>。你想找到最年长的 Paul、Robert 等……你可以这样做:
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);
}
说,我想得到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>转换为Map<String, Integer>。我想在 groupingBy、reduce 和 mapping 的链中完成所有这些工作。
这是“伪代码”:
var mapping = people.stream().collect(groupingBy(Person::getName, reducing(dummy, (p1, p2) -> p1.getAge() < p2.getAge() ? p2 : p1 /*, have to write some other collector factory method here*/)));
我怎样才能做到这一点?
【问题讨论】:
-
看起来collectingAndThen是唯一的方法?我刚刚用谷歌搜索了那个方法。
-
你真的需要3张地图吗?或者您是在问如何以
Map<String, Integer>结尾? -
@shmosel 我不需要 3 张地图,请查看我的代码以查看它返回的类型。我不会在任何地方创建 3 张地图。
-
您的细分不是很准确。这些示例实际上都没有生成任何列表。无论哪种方式,我都不明白这个问题的意义。第一种方式有什么问题?
-
@POrekhov 这个问题是关于 Stream API 的事实已经由
[java-stream]标签给出。无需通过使用[java-8]标记每个[java-stream]问题来承认此API 是在Java 8 中引入的事实。特定于版本的标签用于说明您想要特定于版本的答案。由于 API 可能会发生变化,最值得注意的是,它们会得到扩展,并且使用新的 API 版本可能会有更简单的解决方案,这是一个限制。但是将 API 限制为一个版本,但在示例代码中积极使用更新的功能是令人困惑的。
标签: java java-8 java-stream