Java8で導入されたStreamの distinct()
について調べてみましょう。
1. Stream の distinct() メソッド
distinctの辞書的な意味は「区別できる」です。 Streamでは、distinct()
メソッドはストリームから重複する要素をすべて削除し、新しいストリームを返します。
次の例では、stream1はリストのストリームであり、stream2はstream1から重複が削除された要素のストリームになります。 distinct()
は重複を削除し、新しいストリームを返します。
List<String> strings =
Arrays.asList("google", "apple", "google", "apple", "samsung");
Stream<String> stream1 = strings.stream();
Stream<String> stream2 = stream1.distinct();
stream2.forEach(System.out::println);
Output:
google
apple
samsung
ちなみに、 distinct()
メソッドで重複する要素を確認するとき、同じオブジェクトかどうかを判断する基準は Object.equals(Object)
メソッドです。
上記の例では、Stringクラスは equals()
が既に実装されているので問題はありませんが Custom クラスなら正しく実装が正しいか確認してみる必要はあります。
2. Custom クラスに対する distinct() の使用例
distinct()
で重複を判別する基準が equals()
と呼ばれました。カスタムクラスで equals()
をオーバーライドしない場合は、デフォルトで継承した equals()
を使用します。
もしクラスの特定の要素だけ同じなら、同じオブジェクトと判断したいときは、 equals()
を自分の状況に合わせてオーバーライドしなければなりません。
注意すべき点は、 equals()
をオーバーライドするときに hashCode()
も一緒にオーバーライドしなければなりません。 distinct()
で重複する要素を判別するとき、まず hashCode()
を使ってオブジェクトが異なることを確認し、 equals()
で等しいかどうかチェックするようです。どちらか一方が再定義されていないと、正しく動作しない可能性があります。
次の例では、MyStringというカスタムクラスを定義し、 hashCode()
と equals()
をオーバーライドしました。
public class StreamExample5 {
public static void main(String args[]) {
List<MyString> myStrings =
Arrays.asList(new MyString("google"),new MyString("apple"),
new MyString("google"), new MyString("apple"), new MyString("samsung"));
Stream<MyString> stream3 = myStrings.stream();
Stream<MyString> stream4 = stream3.distinct();
stream4.forEach(System.out::println);
}
public static class MyString {
public String str;
public MyString(String str) {
this.str = str;
}
@Override
public boolean equals(Object o) {
if (o instanceof MyString) {
return str.equals(((MyString) o).str);
}
return false;
}
@Override
public int hashCode() {
return str.hashCode();
}
@Override
public String toString() {
return str;
}
}
}
Output:
google
apple
samsung
Related Posts
- Java - AtomicReference使用方法
- Java - CountDownLatchを使用する方法、および例
- Java - ScheduledThreadPoolExecutor使用方法
- Java - SummaryStatisticsの使用方法(count、min、max、average)
- Java8 - 関数型インタフェース (Functional Interface) について
- Java - String配列をint配列に変換する
- Java - ArrayList要素の値を変更する方法、replaceAll()
- Java - 2つのリストが同じかどうかを比較
- Java - 配列から特定のIndex要素を削除する3つの方法
- Java - HashMapソート、4つの方法
- Java - 文字列を配列に変換する方法
- Java - ArrayListが空であることを確認する3つの方法
- Java - ArrayListの巡回、4つの方法
- Java - ArrayListの最大値、最小 値を見つける
- Java - ArrayListの合計、平均値の計算
- Java - HashMap巡回、3つの方法
- Java - do whileとwhileの違い
- Java - Lambda式と関数型インタフェース
- Java - List empty(null)チェック、3つの方法
- Java - ArrayListの初期化、4つの方法
- Java - Stream.reduce()の使い方と例
- Java - 2つのマップを結合する(merge、putAll)
- Java - java.util.Dateをjava.sql.Dateに変換する
- Java - ArrayListをStringに変換する
- Java - ClassNotFoundExceptionの発生原因と解決策
- Java - 非静的メソッドは静的コンテキストから参照できません
- Java - NoSuchMethodErrorの原因と解決策
- Java - JSONライブラリを使用する方法(JSONObject、JSONArray)
- Java - byte[]配列をFileに保存
- Java - byte[]の配列をStringに変換
- Java - ファイルのアクセス権を確認し、変更
- Java - 一時フォルダ(Temp directory)パスを取得する
- Javaでシェルスクリプトを実行
- Java - Streamを配列に変換する
- Java - リスト重複排除、2つの方法