Повторная карта Java 8 с измененным значением

Я собираюсь понять новые параметры потока Java 8 и лямбда, но все еще есть несколько тонкостей, которые я еще не оборачивал.

Скажем, что у меня есть карта, где ключи - это имена людей. Значение для каждого представляет собой карту возрастов и фактических экземпляров 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/collect/map/flatten/etc. чтобы получить тот же результат? В псевдокоде мое первое наклонение было бы следующим:

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

Этот вопрос должен быть простым без каких-либо трюков или странностей - просто вопрос о том, как я могу полностью использовать Java 8!

Бонус: Скажем, что NavigableMap<Long, Person> выше вместо этого просто a 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)))
                             );

Здесь вместо того, чтобы полагаться на lastEntry, мы ищем ключ max в каждом из внутренних Map s и получаем соответствующее Лицо ключа max.

У меня могут быть некоторые глупые опечатки, так как я их не проверял, в принципе это должно сработать.