Java 8使用修改后的值重新映射

Gar*_*son 17 java collections lambda java-8 java-stream

我即将掌握新的Java 8流和lambda选项,但仍然有一些细微之处,我还没有想到.

假设我有一张地图,其中的键是人的名字.每个名称的值是年龄和Person实例的地图.进一步假设不存在多个具有相同名称和年龄的人.

Map<String, NavigableMap<Long, Person>> names2PeopleAges = new HashMap<String, NavigableMap<Long, Person>>();
Run Code Online (Sandbox Code Playgroud)

在填充该地图(其他地方)之后,我想为每个名称生成另一个最老的人的地图.我想结束一个Map<String, Person>键,其中的键与第一个映射中的键相同,但每个条目的值是值映射的值,其中值映射的键具有最高的数字.

利用对NavigableMap键进行排序的事实,我可以这样做:

Map<String, Person> oldestPeopleByName = new HashMap<String, Person>();
names2PeopleAges.forEach((name, peopleAges) -> {
  oldestPeopleByName.put(name, peopleAges.lastEntry().getValue());
});
Run Code Online (Sandbox Code Playgroud)

问题:我可以用一个Java 8流/ collect/map/flatten/etc替换上面的最后一段代码.操作产生相同的结果?在伪代码中,我的第一个倾向是:

Map<String, Person> oldestPeopleByName = names2PeopleAges.forEachEntry().mapValue(value->value.lastEntry().getValue());
Run Code Online (Sandbox Code Playgroud)

这个问题是直截了当的,没有任何技巧或奇怪 - 只是一个简单的问题,我如何充分利用Java 8!

额外奖励:让我们说NavigableMap<Long, Person>上面只是一个Map<Long, Person>.您是否可以延长第一个答案,以便收集具有最高年龄值的人,现在NavigableMap.lastEntry()不可用?

Era*_*ran 30

您可以创建条目流并将其收集到地图:

Map<String, Person> oldestPeopleByName = 
    names2PeopleAges.entrySet()
                    .stream()
                    .collect (Collectors.toMap(e->e.getKey(),
                                               e->e.getValue().lastEntry().getValue())
                             );
Run Code Online (Sandbox Code Playgroud)

现在,没有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)))
                             );
Run Code Online (Sandbox Code Playgroud)

在这里,我们不是依靠,而是在每个内部s中lastEntry搜索max密钥Map,并获得最大密钥的相应Person.

我可能有一些愚蠢的错别字,因为我实际上没有测试它,原则上它应该工作.