Javaマップで最高値を見つける
1. 概要
このクイックチュートリアルでは、we’ll explore various ways to find the maximum value in a Java Map。 また、Java 8の新機能によってこの操作がどのように簡素化されたかについても説明します。
始める前に、Javaでのobjects are comparedの方法を簡単に要約しましょう。
通常、オブジェクトは、ComparableインターフェイスからメソッドcompareTo()を実装することにより、自然な順序を表現できます。 ただし、自然な順序以外の順序は、Comparatorオブジェクトを介して使用できます。 これらについては、後で詳しく説明します。
2. Java 8より前
まず、Java8の機能なしで最高の価値を見つける方法を探り始めましょう。
2.1. 単純な反復の使用
反復を使用すると、Mapのすべてのエントリを調べて最大値を選択し、現在の最大値を変数に格納できます。
public > V maxUsingIteration(Map map) {
Map.Entry maxEntry = null;
for (Map.Entry entry : map.entrySet()) {
if (maxEntry == null || entry.getValue()
.compareTo(maxEntry.getValue()) > 0) {
maxEntry = entry;
}
}
return maxEntry.getValue();
}
ここでは、Javaジェネリックを利用して、さまざまなタイプに適用できるメソッドを構築しています。
2.2. Collections.max()の使用
次に、Collectionsクラスのユーティリティメソッドmax()を使用して、これを自分で作成する手間を省く方法を見てみましょう。
public > V maxUsingCollectionsMax(Map map) {
Entry maxEntry = Collections.max(map.entrySet(), new Comparator>() {
public int compare(Entry e1, Entry e2) {
return e1.getValue()
.compareTo(e2.getValue());
}
});
return maxEntry.getValue();
}
この例では、compareTo()を介してEntry値の自然な順序を利用したり、まったく別の順序を実装したりできるwe’re passing a Comparator object to max()です。
3. Java 8の後
Java 8の機能により、上記の試みを単純化して、Mapから最大値を複数の方法で取得できます。
3.1. ラムダ式でCollections.max()を使用する
ラムダ式がCollections.max()の呼び出しをどのように単純化できるかを調べることから始めましょう。
public > V maxUsingCollectionsMaxAndLambda(Map map) {
Entry maxEntry = Collections.max(map.entrySet(), (Entry e1, Entry e2) -> e1.getValue()
.compareTo(e2.getValue()));
return maxEntry.getValue();
}
ここでわかるように、lambda expressions save us from defining the full-fledged functional interfaceは、ロジックを定義する簡潔な方法を提供します。 ラムダ式の詳細については、our previous articleも確認してください。
3.2. Streamの使用
Stream APIは、Java 8へのもう1つの追加機能であり、コレクションの操作が大幅に簡素化されています。
public > V maxUsingStreamAndLambda(Map map) {
Optional> maxEntry = map.entrySet()
.stream()
.max((Entry e1, Entry e2) -> e1.getValue()
.compareTo(e2.getValue())
);
return maxEntry.get().getValue();
}
このAPIは、コレクションに対するmap-reduce変換などの多くのデータ処理クエリを提供します。 Here, we’ve used max() over a stream of Map Entryは、削減操作の特殊なケースです。 Stream APIの詳細については、hereをご覧ください。
ここでは、Optional APIも使用しています。これは、Java 8で追加されたコンテナオブジェクトであり、null以外の値が含まれる場合と含まれない場合があります。 Optionalの詳細は、hereで取得できます。
3.3. メソッドリファレンスでのStreamの使用
最後に、メソッド参照がラムダ式の使用をさらに簡素化する方法を見てみましょう。
public > V maxUsingStreamAndMethodReference(Map map) {
Optional> maxEntry = map.entrySet()
.stream()
.max(Comparator.comparing(Map.Entry::getValue));
return maxEntry.get()
.getValue();
}
ラムダ式が単に既存のメソッドを呼び出すだけの場合、メソッド参照により、メソッド名を直接使用してこれを行うことができます。 method referencesの詳細については、this previous articleをご覧ください。
4. 結論
この記事では、Java Mapで最大値を見つける複数の方法を見てきました。そのうちのいくつかは、Java8の一部として追加された機能を使用していました。
いつものように、例のコードはover on GitHubで利用できます。