1. 概要
このチュートリアルでは、2つのリストの共通部分を取得する方法を学習します。
他の多くのものと同様に、これはJava8にストリームが導入されたおかげではるかに簡単になりました。
2. 文字列の2つのリストの共通部分
いくつかの交差を持つStringの2つのListを作成しましょう—両方ともいくつかの重複した要素を持っています:
List<String> list = Arrays.asList("red", "blue", "blue", "green", "red");
List<String> otherList = Arrays.asList("red", "green", "green", "yellow");
そして今ストリームメソッドの助けを借りてリストの共通部分を決定します:
Set<String> result = list.stream()
.distinct()
.filter(otherList::contains)
.collect(Collectors.toSet());
Set<String> commonElements = new HashSet(Arrays.asList("red", "green"));
Assert.assertEquals(commonElements, result);
まず、distinctで重複した要素を削除します。 次に、フィルターを使用して、otherListにも含まれている要素を選択します。
最後に、Collectorを使用して出力を変換します。 交差点には、各共通要素を1回だけ含める必要があります。 順序は重要ではないため、 toSet が最も簡単な選択ですが、toListまたは別のコレクターメソッドを使用することもできます。
詳細については、Java8のコレクターガイドを確認してください。
3. カスタムクラスのリストの共通部分
ListにStringが含まれておらず、作成したカスタムクラスのインスタンスが含まれている場合はどうなりますか? Javaの規則に従う限り、ストリームメソッドを使用したソリューションはカスタムクラスで正常に機能します。
contains メソッドは、特定のオブジェクトがリストに表示されるかどうかをどのように判断しますか? equalsメソッドに基づいています。 したがって、 equals メソッドをオーバーライドし、関連するプロパティの値に基づいて2つのオブジェクトを比較するようにする必要があります。
たとえば、幅と高さが等しい場合、2つの長方形は等しくなります。
equals メソッドをオーバーライドしない場合、クラスは親クラスのequals実装を使用します。 1日の終わり、つまり継承チェーンで、Objectクラスのequalsメソッドが実行されます。 次に、2つのインスタンスは、ヒープ上のまったく同じオブジェクトを参照している場合にのみ等しくなります。
equals メソッドの詳細については、 Java equals()およびhashCode()コントラクトに関する記事を参照してください。
4. 結論
この簡単な記事では、ストリームを使用して2つのリストの共通部分を計算する方法を見てきました。 以前は非常に面倒でしたが、Java Stream APIの使い方を知っていれば、かなり簡単な操作が他にもたくさんあります。 Javaストリームを使用したその他のチュートリアルをご覧ください。
コード例は、GitHubでから入手できます。