第7章. ストリームを使う
この作品はAIを使って翻訳されている。ご意見、ご感想をお待ちしている:translation-feedback@oreilly.com
ストリームは、Java 8で導入された多くの関数機能を利用し、データを処理するための宣言的な方法を提供する。 ストリームAPIは多くのユースケースをカバーしているが、それらを最大限に活用するためには、さまざまな演算子や利用可能なヘルパークラスがどのように機能するかを知っておく必要がある。
第6章では、Streamsの基礎を説明することに集中した。 この章では、それを基礎として、様々なユースケースにおけるStreamsの作成方法と操作方法を説明する。
プリミティブ・ストリーム
Javaでは、ジェネリックスは(まだ)オブジェクトベースの型にしか使えない。1そのため、int のようなプリミティブ値のシーケンスにStream<T> を使うことはできない。 ストリームでプリミティブ型を使うには、2つの選択肢しかない:
-
オートボクシング
-
特殊化ストリーム・バリエーション
Javaのオートボクシング・サポート(プリミティブ型と、int やIntegerのようなオブジェクト・ベースの対応する型との間の自動変換)は、以下のように自動的に機能するため、簡単な回避策のように見えるかもしれない:
Stream<Long>longStream=Stream.of(5L,23L,42L);
しかし、オートボックスには複数の問題がある。 ひとつは、プリミティブ型を直接使う場合と比べ、プリミティブ値からオブジェクトへの変換に伴うオーバーヘッドだ。 通常、このオーバーヘッドは無視できるほど小さい。 しかし、データ処理パイプラインでは、このようなラッパー型の頻繁な生成によるオーバーヘッドが蓄積し、全体的なパフォーマンスを低下させる可能性がある。
プリミティブ・ラッパーのもう1つの問題点は、null 要素の可能性である。プリミティブからオブジェクト型への直接変換は、null になることはないが、パイプラインのどの演算も、プリミティブの代わりにラッパー型を扱わなければならない場合、null を返す可能性がある。
これを緩和するために、JDKの他の関数と同様に、ストリームAPIは、表7-1にリストされているように、オートボクシングに依存しないプリミティブ型int 、long 、double のための特殊化された亜種を持っている。
| プリミティブ・タイプ | プリミティブ・ストリーム | ボックスド・ストリーム |
|---|---|---|
|
|
|
|
|
|
|
|
|
プリミティブストリームで利用可能な演算子は、ジェネリックストリームと似ていますが、プリミティブ関数インタフェースを使用します。 例えば、IntStream は、Stream<T> と同様に、要素を変換するためのmap 演算子を提供します。Stream<T> とは異なり、これを行うために必要な高階関数は、特殊化されたバリアントです。IntUnaryOperatorこの関数は、以下の簡略化されたインタフェース宣言が示すように、int を受け取って返す:
@FunctionalInterfacepublicinterfaceIntUnaryOperator ...