web-dev-qa-db-ja.com

Java 8変更された値で再マップ

新しいJava 8ストリームとラムダオプションを理解しようとしていますが、まだ気に留めていない微妙な点がいくつかあります。

キーが人々の名前であるマップを持っているとしましょう。各名前の値は、年齢と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 stream/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()が利用できなくなったので、最も高い年齢の値を持つ人を収集するように最初の回答を拡張できますか?

16
Garret Wilson

エントリのストリームを作成し、それをマップに収集できます。

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に依存する代わりに、内部maxsのそれぞれでMapキーを検索し、対応する最大キーのPersonを取得します。

私は実際にそれをテストしていないので、いくつかの愚かなタイプミスがあるかもしれません、原則としてそれは動作するはずです。

28
Eran