初心者向けのJavaストリーム:Javaでのストリームの使用の概要

Java 8ストリームを使用すると、開発者は、事前定義された一連の操作を使用して、大規模なコレクションから正確なデータを抽出できます。

Java 8のリリース前は、Javaで「ストリーム」という用語を使用すると、自動的にI / Oに関連付けられていました。ただし、Java 8では、一般に「ストリームパイプライン」と呼ばれるものにチェーンされた一連の計算ステップと呼ばれるストリームが導入されました。

この記事では、Java 8ストリームを紹介し、それらがプロジェクトでどのように役立つかを示します。

ストリームとは何ですか?

ストリームは、ソースを取得し、特定のデータを抽出するための一連の操作を実行し、そのデータをアプリケーションに提供して使用するJavaインターフェースです。基本的に、一般化されたデータのコレクションから特殊なデータを抽出できます。

ストリームのしくみ

ストリームパイプラインは常にソースから始まります。ソースのタイプは、処理しているデータのタイプによって異なりますが、最も一般的な2つは、配列とコレクションです。

コレクションを初期ストリームに変換するには、 stream()関数をソースに追加する必要があります。これにより、ソースがストリームパイプラインに配置され、そこでいくつかの異なる中間操作( filter()sort()など)を操作できます。

必要なすべての中間操作が実行された後、ターミナル操作( forEach()などを導入できます。これにより、ソースから以前に抽出されたデータが生成されます。

ストリームのない生活

Java 8は2014年にリリースされましたが、それ以前は、Java開発者は一般的なデータのコレクションから特殊なデータを抽出する必要がありました。

乱数と組み合わせて一意の文字列値を形成するランダム文字のリストがあるが、文字「C」で始まる値のみが必要であり、結果を昇順で並べたいとします。これは、ストリームなしでそのデータを抽出する方法です。

関連: Javaでの文字列の使用について知っておくべきこと

ストリームを使用しない値のフィルタリングと並べ替えの例


import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
//declare and initialize the array list
List<String> randomValues = Arrays.asList(
"E11", "D12", "A13", "F14", "C15", "A16",
"B11", "B12", "C13", "B14", "B15", "B16",
"F12", "E13", "C11", "C14", "A15", "C16",
"F11", "C12", "D13", "E14", "D15", "D16"
);
//declare the array list will store needed values
List<String> requiredValues = new ArrayList<>();
//extracting the required values and storing them in reqquiredValues
randomValues.forEach(value -> {
if(value.startsWith("C")) {
requiredValues.add(value);
}
});
//sort the requiredValues in ascending order
requiredValues.sort((String value1, String value2) -> value1.compareTo(value2));
//print each value to the console
requiredValues.forEach((String value) -> System.out.println(value));
}
}

また、ストリームを使用している場合でも、他の抽出方法を使用している場合でも、配列リストを宣言して初期化する必要があります。ストリームを使用している場合に行う必要がないのは、必要な値を保持するための新しい変数を宣言することでも、上記の例で他の5行以上のコードを作成することでもありません。

関連: Javaで配列の操作を作成および実行する方法

上記のコードは、コンソールに次の出力を生成します。

 
C11
C12
C13
C14
C15
C16

ストリームのある生活

プログラミングでは、効率は大幅に少ないコードで同じ結果を生成することを意味します。これはまさに、ストリームパイプラインがプログラマーのために行うことです。したがって、次に誰かが尋ねたとき、「プロジェクトでストリームを使用することが重要なのはなぜですか?」簡単に言えば、「ストリームは効率的なプログラミングをサポートします。」

上記の例を続けると、これがストリームの導入によってプログラム全体がどのように変換されるかを示しています。

ストリームの例を使用した値のフィルタリングと並べ替え


import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
//declare and initialize the array list
List<String> randomValues = Arrays.asList(
"E11", "D12", "A13", "F14", "C15", "A16",
"B11", "B12", "C13", "B14", "B15", "B16",
"F12", "E13", "C11", "C14", "A15", "C16",
"F11", "C12", "D13", "E14", "D15", "D16"
);
//retrieves only values that start with C, sort them, and print them to the console.
randomValues.stream().filter(value->value.startsWith("C")).sorted().forEach(System.out::println);
}
}

上記のコードは、ストリームインターフェイスがいかに強力であるかを示しています。ランダムな配列値のリストを取得し、 stream()関数を使用してストリームに変換します。次に、 filter()関数を使用して、ストリームは必要な値( Cで始まるすべての値)を含む配列リストに縮小されます。

上記の例でわかるように、 C値は配列リストにランダムに配置されています。パイプラインのこの時点でストリームを印刷する場合は、値C15が最初に印刷されます。したがって、 sort()関数がストリームパイプラインに導入され、新しい配列が昇順で再配置されます。

ストリームパイプラインの最後の関数はforEach()関数です。これは、ストリームパイプラインを停止するために使用される端末関数であり、コンソールで次の結果を生成します。

 
C11
C12
C13
C14
C15
C16

ストリーム中間操作

ストリームパイプラインで使用できる中間操作の広範なリストがあります。

ストリームパイプラインは常に単一のソースとstream()関数で始まり、常に単一のターミナル操作で終わります(ただし、選択できるものはいくつかあります)。ただし、これら2つのセクションの間に、6つの中間操作のリストがあります。使用できます。

上記の例では、これらの中間操作のうち2つだけが使用されています— filter()sort() 。選択する中間操作は、実行するタスクによって異なります。

上記の配列リストの「C」で始まる値のいずれかが小文字であり、それらに対して同じ中間操作を実行した場合、次の結果が得られます。

小文字の値に対するフィルターおよびソート操作の実行例


import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
//declare and initialize the array list
List<String> randomValues = Arrays.asList(
"E11", "D12", "A13", "F14", "C15", "A16",
"B11", "B12", "c13", "B14", "B15", "B16",
"F12", "E13", "C11", "C14", "A15", "c16",
"F11", "C12", "D13", "E14", "D15", "D16"
);
//retrieves only values that start with C, sort them, and print them to the console.
randomValues.stream().filter(value->value.startsWith("C")).sorted().forEach(System.out::println);
}
}

上記のコードは、コンソールに次の値を生成します。

 
C11
C12
C14
C15

上記の出力の唯一の問題は、配列リスト内のすべてのC値を正確に表していないことです。この小さなエラーを修正する良い方法は、ストリームパイプラインに別の中間操作を導入することです。この操作はmap()関数として知られています

Map関数の例の使用


import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
//declare and initialize the array list
List<String> randomValues = Arrays.asList(
"E11", "D12", "A13", "F14", "C15", "A16",
"B11", "B12", "c13", "B14", "B15", "B16",
"F12", "E13", "C11", "C14", "A15", "c16",
"F11", "C12", "D13", "E14", "D15", "D16"
);
//transforms all lower case characters to upper case,
//retrieves only values that start with C, sort them, and print them to the console.
randomValues.stream().map(String::toUpperCase).filter(value->value.startsWith("C")).sorted().forEach(System.out::println);
}
}

map()関数は、オブジェクトをある状態から別の状態に変換します。上記の例では、配列リスト内のすべての小文字を大文字に変換します。

filter ()関数の直前にmap()関数を配置すると、配列リストからCで始まるすべての値が取得されます。

上記のコードは、コンソールに次の結果を生成し、配列リスト内のすべてのC値を正常に表します。

 
C11
C12
C13
C14
C15
C16

アプリケーションで使用できる他の3つの中間操作は次のとおりです。

  • ピーク()
  • limit()
  • スキップ()

Java 8ストリームは、効率的なコードの作成を容易にします

Java 8ストリームを使用すると、1行のコードで大規模なソースから特定の関連データを抽出できます。初期のstream()関数とターミナル演算子が含まれている限り、目的に合った出力を提供する中間操作の任意の組み合わせを使用できます。

filter()関数で囲まれたコード行について疑問がある場合は、これは「ラムダ式」として知られています。ラムダ式はJava8で導入されたもう1つの機能であり、役立つと思われるナゲットがたくさんあります。