不変コレクションへのJavaストリームを集める
1前書き
この簡単な記事では、標準のコレクターは可変データ構造でのみ機能するため、特別なアプローチを必要とする、不変のコレクションにJavaのストリームを集めるさまざまな方法について説明します。
2 Mavenの依存関係
GoogleのGuavaライブラリを使用して、いくつかの例を示します。
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>22.0</version>
</dependency>
この依存関係の最新バージョンはhttps://search.maven.org/classic/#search%7C1%7Cg%3A%22com.google.guava%22%20AND%20a%3A%22guava%22から入手できます。[ここに]。
3 Javaの
collectingAndThen()
を使う
Javaの
Collectors
クラスの
collectingAndThen()メソッドは、
Collector
、および
Collectorから返される結果に適用される
finisher
Function
を受け入れます。
@Test
public void whenUsingCollectingToImmutableList__thenSuccess() {
List<String> givenList = Arrays.asList("a", "b", "c");
List<String> result = givenList.stream()
.collect(collectingAndThen(toList(), ImmutableList::copyOf));
System.out.println(result.getClass());
}
-
toCollection
__()Collector
__を直接使用することはできないので、一時的なリストに要素を収集し、それから不変リストを作成する必要があります。
この例では、
toList()
コレクターを使用して
Stream
を
List
に変換し、次に
ImmutableList
を作成しています。
ImmutableList
は、Guavaライブラリの一部です。出力をコンソールに記録すると、基礎となるクラスが表示されます。
出力をコンソールに記録すると、基礎となる
List
実装のクラスが得られます。
class com.google.common.collect.RegularImmutableList
4グアバの
Collectors
を使う
Guava 21以降、すべての不変クラスには、標準の
Collectorsと同じくらい簡単に使用できる
Collector__が付属しています。
@Test
public void whenCollectToImmutableList__thenSuccess() {
List<Integer> list = IntStream.range(0, 9)
.boxed()
.collect(ImmutableList.toImmutableList());
}
結果のインスタンスは
RegularImmutableList
です。
class com.google.common.collect.RegularImmutableList
5カスタムコレクターの構築
それでは、さらに一歩進めて、カスタムの
Collector
を実装しましょう。
この目的を達成するために、静的な
Collector.of()
メソッドを使用します。
public static <T> Collector<T, List<T>, List<T>> toImmutableList() {
return Collector.of(ArrayList::new, List::add,
(left, right) -> {
left.addAll(right);
return left;
}, Collections::unmodifiableList);
}
カスタム
Collectors
の実装についてもっと学ぶために、
この記事
のセクション4を見てください。以上です。
上記のメソッドはカスタムクラスの一部です
他の組み込み
Collectors
と同じように使用できます。
@Test
public void whenCollectToMyImmutableListCollector__thenSuccess() {
List<String> givenList = Arrays.asList("a", "b", "c", "d");
List<String> result = givenList.stream()
.collect(MyImmutableListCollector.toImmutableList());
}
最後に、出力を確認しましょう。
class java.util.Collections$UnmodifiableRandomAccessList
5.1.
MyImmutableListCollector
ジェネリック
を作る
私たちの実装には1つの制限があります – それは
ArrayList
によって支えられた不変のインスタンスを常に返します。ただし、わずかな改善で、このコレクターにユーザー指定のタイプを返させることができます。
public static <T, A extends List<T>> Collector<T, A, List<T>> toImmutableList(
Supplier<A> supplier) {
return Collector.of(
supplier,
List::add, (left, right) -> {
left.addAll(right);
return left;
}, Collections::unmodifiableList);
}
メソッド実装で
仕入先を決定する代わりに、ユーザから
仕入先を要求しています。
@Test
public void whenPassingSupplier__thenSuccess() {
List<String> givenList = Arrays.asList("a", "b", "c", "d");
List<String> result = givenList.stream()
.collect(MyImmutableListCollector.toImmutableList(LinkedList::new));
}
ArrayList
の代わりに
LinkedList
を使用していることに注意してください。これを実行して結果を確認しましょう。
class java.util.Collections$UnmodifiableList
今回は、
UnmodifiableRandomAccessList
ではなく
UnmodifiableList
を取得しました。
6. 結論
この短い記事では、
Stream
を集めて不変の
Collection
にするさまざまな方法を説明しました。
この記事の完全なソースコードをチェックアウトしてください。