JavaStreamAPIのDistinctBy
1. 概要
リスト内のさまざまな要素を検索することは、プログラマーとして私たちが通常直面する一般的なタスクの1つです。 Streamsを含むJava8以降、機能的アプローチを使用してデータを処理するための新しいAPIがあります。
この記事では、リスト内のオブジェクトの特定の属性を使用してコレクションをフィルタリングするためのさまざまな代替方法を示します。
2. StreamAPIの使用
Stream APIは、 Objectクラスのequals()メソッドに基づいて、リストのさまざまな要素を返す distinct()メソッドを提供します。
ただし、特定の属性でフィルタリングする場合は、柔軟性が低下します。 私たちが持っている選択肢の1つは、状態を維持するフィルターを作成することです。
2.1. ステートフルフィルターの使用
考えられる解決策の1つは、ステートフルな述語:を実装することです。
public static <T> Predicate<T> distinctByKey(
Function<? super T, ?> keyExtractor) {
Map<Object, Boolean> seen = new ConcurrentHashMap<>();
return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
テストするには、属性 age 、 email 、およびnameを持つ次のPersonクラスを使用します:
public class Person {
private int age;
private String name;
private String email;
// standard getters and setters
}
また、 name でフィルタリングされた新しいコレクションを取得するには、次を使用できます。
List<Person> personListFiltered = personList.stream()
.filter(distinctByKey(p -> p.getName()))
.collect(Collectors.toList());
3. Eclipseコレクションの使用
Eclipseコレクションは、Javaでストリームおよびコレクションを処理するための追加のメソッドを提供するライブラリです。
3.1. ListIterate.distinct()の使用
The ListIterate.distinct() メソッドを使用すると、 ストリームいろいろ使って
Personの名でフィルタリングする場合:
List<Person> personListFiltered = ListIterate
.distinct(personList, HashingStrategies.fromFunction(Person::getName));
または、使用する属性がプリミティブ(int、long、double)の場合、次のような特殊な関数を使用できます。
List<Person> personListFiltered = ListIterate.distinct(
personList, HashingStrategies.fromIntFunction(Person::getAge));
3.2. Mavenの依存関係
プロジェクトでEclipseコレクションを使用するには、pom.xmlに次の依存関係を追加する必要があります。
<dependency>
<groupId>org.eclipse.collections</groupId>
<artifactId>eclipse-collections</artifactId>
<version>8.2.0</version>
</dependency>
Eclipseコレクションライブラリの最新バージョンは、 MavenCentralリポジトリにあります。
このライブラリの詳細については、この記事にアクセスしてください。
4.4。 Vavrを使用する(J avaslang )。
これは、不変のデータと機能制御構造を提供するJava8用の機能ライブラリです。
4.1. List.distinctByを使用する
リストをフィルタリングするために、このクラスは、 distinctBy()メソッドを持つ独自のListクラスを提供します。これにより、含まれるオブジェクトの属性でフィルタリングできます。
List<Person> personListFiltered = List.ofAll(personList)
.distinctBy(Person::getName)
.toJavaList();
4.2. Mavenの依存関係
プロジェクトでVavrを使用するために、pom.xmlに次の依存関係を追加します。
<dependency>
<groupId>io.vavr</groupId>
<artifactId>vavr</artifactId>
<version>0.9.0</version>
</dependency>
Vavrライブラリの最新バージョンは、 MavenCentralリポジトリにあります。
このライブラリの詳細については、この記事にアクセスしてください。
5. StreamExの使用
このライブラリは、Java8ストリーム処理に役立つクラスとメソッドを提供します。
5.1. StreamEx.distinctを使用する
提供されるクラス内には、 StreamEx があります。このメソッドには、 distinct メソッドがあり、区別したい属性への参照を送信できます。
List<Person> personListFiltered = StreamEx.of(personList)
.distinct(Person::getName)
.toList();
5.2. Mavenの依存関係
プロジェクトでStreamExを使用するために、pom.xmlに次の依存関係を追加します。
<dependency>
<groupId>one.util</groupId>
<artifactId>streamex</artifactId>
<version>0.6.5</version>
</dependency>
StreamExライブラリの最新バージョンは、 MavenCentralリポジトリにあります。
6. 結論
このクイックチュートリアルでは、標準のJava 8 APIを使用した属性と、他のライブラリを使用した追加の代替手段に基づいて、ストリームのさまざまな要素を取得する方法の例を検討しました。
いつものように、完全なコードはGitHubでから入手できます。