このJava 8ストリームのcollect()メソッドを理解するにはどうすればよいですか?


12

私はint配列をListに変換しようとしていましたが、Java 8 Streamを使用するというなじみのないルートを取り、これを思いつきました

Arrays.stream(arr).boxed().collect(Collectors.toList());

私はまだこの行を完全に理解するのにまだ苦労しています、ほとんどの場合、

  1. Collectors.toList()この場合、なぜArrayList<Integer>実装Listインターフェースが返されるのですか?なぜ、LinkedList<Integer>またはListインターフェイスに準拠していない他の総称クラスですか?ここでは、APIリストのセクションでArrayListについて簡単に説明している以外は何も見つかりません。

  2. 左のパネルは どういう意味ですか?明らかに、一般的な戻り値の型です(このコードでは)。そして、私はメソッドのジェネリック型引数だと思いますが、それらはどのように指定されていますか?Collectorインターフェースのドキュメントを調べましたが、吸収できませんでした。ここに画像の説明を入力してください Stream.collect()RArrayList<Integer><R, A>


2
1.明らかに、実際のリストを内部で使用しています。しかし、APIが実際の基になるListタイプを明らかにすることは賢明ではありません。それ以来、彼らはもう実装を変更することはできません。一般的に、インターフェースのみを公開し、実際の基本型は公開しないことがしばしば良い考えです。2. Rは、結果の型のジェネリック型です。Aコレクターの中間累積型のジェネリック型。これは、コレクターがどのように動作するかの詳細な実装です。並列処理の場合も、分割して征服し、最初に中間タイプに収集します。
Zabuzard

10
LinkedListが実際に必要になることはほとんどありません。Josh Blochによる「私が書いたもので、使用したことはない」というツイートがあります。
アンディターナー

4
Collectors.toList()この場合、なぜが返されるのかArrayList<Integer>」が返されない場合がありますArrayListList実装はされ未定義あなたはそれを返すどのような実装に依存することはできませんので、。javadocが言うように、「返されるリストのタイプ、変更可能性、直列化可能性、またはスレッドセーフ性は保証されません。」
Andreas

3
およびorをtoList()返さない-はを返し、最終的にaを作成して返します-また、ドキュメントには次のように記載されています。返されたリストをさらに制御する必要がある場合は、toCollection(Supplier) ....を使用してください。 "ArrayListListCollectorList
user85421-Baned

回答:


18
  1. これはデフォルトの実装です。ArrayListが使用されます。これは、ほとんどのユースケースで最適であるためですが、適切でない場合は、いつでも独自のコレクターを定義して、Collection希望するファクトリーを提供できます。

    Arrays.stream(arr).boxed().collect(toCollection(LinkedList::new));
  2. はい、AそしてRこの方法の一般的なパラメータである、R戻り型であり、T入力タイプであり、A要素の収集プロセス全体に現れるが(表示されない可能性があり、この機能に関係しない)ことは、中間型です。の最初Collectorのjavadocはこれらのタイプを定義します(それらはドキュメント全体で一貫しています)。

    T-リダクション操作への入力要素のタイプ
    A- リダクション操作の変更可能な累積タイプ(実装の詳細として隠されることが多い)
    R-リダクション操作の結果タイプ


なるほど、分かりました。List<Integer> myList = Arrays.stream(arr).boxed().collect(Collectors.toList());myListのListインターフェースで宣言されたメソッドのみに固執して呼び出す必要があると思います。それ以外の場合、OracleがJava8u1024または15のデフォルト実装を変更することを決定した場合、私は潜在的に自分自身を危険にさらすことになりますか?
user3207158

2
@ user3207158メソッドはを返すためList、使用される実装が何であっても、動作は同じです。新しいバージョンのJavaでインターフェースが変更されることはほとんどありません。
Andronicus

1
  1. この場合にCollectors.toList()がArrayList実装のListインターフェースを返すのはなぜですか?

メソッドの定義が示唆するように、それはコレクターのサプライヤーをとして持つコレクターの実装を返しますArrayList。したがって、Collectors.toList常にArrayList collector(While it's arguable why toList not toArrayList word is used in method name)を返すことは、以下のメソッド定義から非常に明確です。

public static <T>
    Collector<T, ?, List<T>> toList() {
        return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
                                   (left, right) -> { left.addAll(right); return left; },
                                   CH_ID);
    }
  1. 左側のパネルの<R, A> R collect(Collector<? super T, A, R> collector)意味は何ですか

ドキュメントのコメントを参照すると、これらのジェネリック型が何であるかが正確に示されています。

/*
      @param <R> the type of the result
      @param <A> the intermediate accumulation type of the {@code Collector}
      @param collector the {@code Collector} describing the reduction
      @return the result of the reduction
*/
 <R, A> R collect(Collector<? super T, A, R> collector);

ありがとうございます。Collectors.toList()(最初のスニペット)のソースコードはどこで入手しましたか?openjdkですか?
user3207158

1
番号!私は私のインテリjでソースコードをダウンロードしました
Vinay Prajapati
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.