我即将掌握新的Java 8流和lambda选项,但仍有一些细微之处尚未解开。
假设我有一张地图,其中的键是人的名字。每个名称的值是年龄和Person
个实例的地图。进一步假设不存在多个具有相同名称和年龄的人。
Map<String, NavigableMap<Long, Person>> names2PeopleAges = new HashMap<String, NavigableMap<Long, Person>>();
在填充该地图(其他地方)之后,我想为每个名称生成另一个最老人的地图。我想结束一个Map<String, Person>
,其中的键与第一个映射中的键相同,但每个条目的值是值映射的值,其中值映射的键具有最高的数字
利用NavigableMap
对其键进行排序的事实,我可以这样做:
Map<String, Person> oldestPeopleByName = new HashMap<String, Person>();
names2PeopleAges.forEach((name, peopleAges) -> {
oldestPeopleByName.put(name, peopleAges.lastEntry().getValue());
});
问题:我可以用一个Java 8流/ collect / map / flatten / etc替换上面的最后一段代码。操作产生相同的结果?在伪代码中,我的第一个倾向是:
Map<String, Person> oldestPeopleByName = names2PeopleAges.forEachEntry().mapValue(value->value.lastEntry().getValue());
这个问题是直截了当的,没有任何诡计或奇怪的问题 - 只是一个关于如何充分利用Java 8的简单问题!
加分:让我们说上面的NavigableMap<Long, Person>
只是Map<Long, Person>
。您是否可以延长第一个答案,以便收集具有最高年龄值的人,现在NavigableMap.lastEntry()
不可用?
答案 0 :(得分:27)
您可以创建条目流并将其收集到地图:
Map<String, Person> oldestPeopleByName =
names2PeopleAges.entrySet()
.stream()
.collect (Collectors.toMap(e->e.getKey(),
e->e.getValue().lastEntry().getValue())
);
现在,没有lastEntry
:
Map<String, Person> oldestPeopleByName =
names2PeopleAges.entrySet()
.stream()
.collect (Collectors.toMap(e->e.getKey(),
e->e.getValue().get(e.getValue().keySet().stream().max(Long::compareTo)))
);
此处,我们不是依赖lastEntry
,而是在每个内部max
中搜索Map
密钥,并获取最大密钥的相应Person。
我可能有一些愚蠢的错别字,因为我实际上没有测试它,原则上它应该有效。