2016-08-15 3 views
6

(これはおそらくhttps://stackoverflow.com/a/30312177/160137に関連していますが、私はまだそれを得られないのではないかと思いますので、私はこのように質問しています。 )なぜCollectors.toList()はプリミティブコレクションで機能しませんか?

私はストリームを持っているとき、通常、私はコレクタークラスの静的メソッドのいずれかを使用してコレクションに変換することができます。同様のプロセスのように、しかし、プリミティブストリーム上では動作しません

List<String> strings = Stream.of("this", "is", "a", "list", "of", "strings") 
    .collect(Collectors.toList()); 

を他の人は気付いた:

IntStream.of(3, 1, 4, 1, 5, 9) 
    .collect(Collectors.toList()); // doesn't compile 
IntStream.of(3, 1, 4, 1, 5, 9) 
    .boxed() 
    .collect(Collectors.toList()); 

をか私はこれを行うことができます:私が代わりにこれを行うことができます

IntStream.of(3, 1, 4, 1, 5, 9) 
    .collect(ArrayList<Integer>::new, ArrayList::add, ArrayList::addAll); 

質問は、ある理由Collectors.toList(ちょうどそのプリミティブのストリームのために行う)しないのですか?ラップされた型を指定する方法がないのでしょうか?もしそうなら、なぜこの機能が働かないのでしょうか?

IntStream.of(3, 1, 4, 1, 5, 9) 
    .collect(Collectors.toCollection(ArrayList<Integer>::new)); // nope 

洞察力があれば分かります。

+9

(Java-8の場合でも) 'List 'はありません。プリミティブ型**は**オブジェクトではありません。 –

+3

シグネチャ内のジェネリックはプリミティブ型では機能しません。このように単純です。 – Dici

+4

明示的に 'boxed()'を呼び出すことと、プリミティブストリームでボックス化されたコレクタを使用することには機能的な違いはありません。なぜそれが利便性のために許されていなかったのかを尋ねるなら、おそらくデザイナーはボクシングを容易に明らかにしたいと思った。 – shmosel

答えて

3

まあ、IntStreamが暗黙のボクシングを実行する署名
<R,A> R collect(Collector<? super Integer,A,R> collector)と方法を提供させても問題ないだろう。 return boxed().collect(collector);のように簡単に実装できます。

質問は「なぜそれを行うべきか」、またはそれ以外の方法である:なぜプリミティブストリームのスペシャライゼーションが存在するのか?

これは、パフォーマンス上の理由から、ボクシングオーバーヘッドなしのストリーム操作を提供するためだけに存在します。したがって、これらのすべてについては、単にインターフェイスに存在する操作を含めないようにする意思決定は、単にboxed().genericOperation(…)を呼び出すことができます。

answer, you have linkedは、関連しているが異なる考え方に対応しています。 Collectorを受け入れないcollectメソッドを提供することですが、Collector.ofIntのようなプリミティブな特殊化は、ボックス化されていない値をList<Integer>という形で生成するコレクタに対してはintの値を集めることができますが、利点はありません。 あらかじめ組み立てられたコレクターの中には、ほんのわずかしかボクシングを避けることができませんでした。それらの全ては(count()sum()min()max()summaryStatistics()、...)

これは、クラス/インタフェースと潜在的なパフォーマンスゲインの数の間のトレードオフプリミティブのストリームに明示的な端末操作として提供されます。一般的なストリームの場合、IntStream,LongStreamおよびDoubleStreamを作成することが決定されましたが、コレクタの場合は、そのような特殊化を追加しないことが決定されました。

1

プリミティブ型の場合List<>は最適次善策です。したがって、toArrayは、十分かつ適切な(=最適な使用)とみなされた。

int[] array = IntStream.of(3, 1, 4, 1, 5, 9).toArray(); 
1
IntStream.of(3, 1, 4, 1, 5, 9) 
    .collect(Collectors.toList()); // doesn't compile 

ストリームはint、オブジェクトを想定toList()一般的な方法です。勝ち目がない。

IntStream.of(3, 1, 4, 1, 5, 9) 
    .boxed() 
    .collect(Collectors.toList()); 

ストリームはInteger、オブジェクトを想定toList()一般的な方法です。一致!

IntStream.of(3, 1, 4, 1, 5, 9) 
    .collect(ArrayList<Integer>::new, ArrayList::add, ArrayList::addAll); 

ストリームはintであり、それはIntegerに、一般的な方法toList()を固定ようなものです。 IntStreamにコレクタを受け入れるメソッドcollect()がないことを除けば、3パラメータのメソッドのみです。

関連する問題