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

2022-09-01 20:24:57

我即将掌握新的Java 8流和lambda选项,但仍有一些微妙之处我还没有考虑过。

假设我有一张地图,其中键是人名。每个名称的值都是年龄和实例的映射。进一步假设不存在一个以上具有相同姓名和年龄的人。Person

Map<String, NavigableMap<Long, Person>> names2PeopleAges = new HashMap<String, NavigableMap<Long, Person>>();

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

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

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

问题:我是否可以将上面的最后一段代码替换为单个 Java 8 流/收集/映射/扁平化/等操作以产生相同的结果?在伪代码中,我的第一个倾向是:

Map<String, Person> oldestPeopleByName = names2PeopleAges.forEachEntry().mapValue(value->value.lastEntry().getValue());

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

奖金:假设上述内容只是一个 .您能否扩展第一个答案,以便它收集年龄值最高的人,现在不可用?NavigableMap<Long, Person>Map<Long, Person>NavigableMap.lastEntry()


答案 1

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

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)))
                             );

在这里,我们不依赖于 ,我们在每个内部 s 中搜索密钥,并获取 max 密钥的相应 Person。lastEntrymaxMap

我可能有一些愚蠢的拼写错误,因为我还没有真正测试过它,原则上它应该有效。


答案 2