開発者ドキュメント

不変コレクションへの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

にするさまざまな方法を説明しました。

この記事の完全なソースコードをチェックアウトしてください。

モバイルバージョンを終了