JavaのStream APIでリストを操作するサンプルです。
目次
Stream APIとは
- リストなどのコレクション、配列、ファイル等に使用します。
- 例:リスト等を指定してストリームを生成し、そのストリームに対して処理します。
→Streamを生成→中間操作→終端操作 - 並列処理を行うこともできます。
- 並列で処理を行うため値が変わらない変数のみアクセス可能です。
→外部のローカル変数に対してアクセスできるのは再代入不可のfinal変数のみです。
→for文では外部のローカル変数にアクセスできます。
コレクションでストリームを使用する
- コレクションではCollectionインターフェースのstreamメソッドを使用します。
- ArrayListなどのコレクションのクラスは、Collectionインターフェースを実装しているのでstreamメソッドを使用できます。
- 以下は、OracleのJava8のCollectionクラスのstreamメソッドのリンクです。
https://docs.oracle.com/javase/jp/8/docs/api/java/util/Collection.html#stream--
要素がint型でストリームを使用する場合
要素がint型の場合は、intstreamを使用します。
Java Stream APIで数値を合計する(IntStream)
各要素を処理する(map)
List<String> c = new ArrayList<>(Arrays.asList("赤", "黄", "青"));
c.stream()
.map(a -> a + "です")
.forEach(System.out::println); //赤です 黄です 青です
mapメソッドで各要素に文字列を追加しています。4,5行目はメソッドチェーンです。
各要素を条件で判定して抽出する(filter)
List<String> c = new ArrayList<>(Arrays.asList("aa", "ab", "ac"));
c.stream()
.filter(a -> a.startsWith("ab"))
.forEach(System.out::println); //ab
filterメソッドで各要素を条件で判定してtrueのものを抽出しています。
startWithメソッドは、文字列の先頭が引数の値と一致した場合trueを返します。
要素の重複をなくす(distinct)
List<String> c = new ArrayList<>(Arrays.asList("A", "A", "B"));
c.stream()
.distinct()
.forEach(System.out::println); //A B
distinctメソッドは、重複をなくします。
要素を並び替える(sorted)
List<String> c = new ArrayList<>(Arrays.asList("aa", "zz", "cc"));
c.stream()
.sorted()
.forEach(System.out::println); // aa cc zz
c.stream()
.sorted(Comparator.reverseOrder())
.forEach(System.out::println); // zz cc aa
sortedメソッドに引数がない場合、自然順序の昇順になります。
sortedメソッドの引数にComparatorインターフェースのstaticメソッドのreverseOrderメソッドを指定すると自然順序の逆になります。
以下は、Java8のComparatorインターフェースのreverseOrderメソッドのリンクです。
https://docs.oracle.com/javase/jp/8/docs/api/java/util/Comparator.html#reverseOrder--
要素数を制限する(limit)
List<String> c = new ArrayList<>(Arrays.asList("赤", "黄", "青"));
c.stream()
.limit(2)
.forEach(System.out::println); // 赤 黄
limitは引数の値の要素数に制限されます。
要素数をスキップする(skip)
List<String> c = new ArrayList<>(Arrays.asList("赤", "黄", "青"));
c.stream()
.skip(2)
.forEach(System.out::println); // 青
skipは引数の値の要素数をスキップします。
要素数を取得する(count)
List<String> c = new ArrayList<>(Arrays.asList("赤", "黄", "青"));
long a = c.stream().count();
System.out.println(a); // 3
countは、要素数を返します。
要素数分繰り返す(forEach)
List<String> c = new ArrayList<>(Arrays.asList("赤", "黄", "青"));
c.stream()
.forEach(System.out::println); // 赤 黄 青
forEachは要素数分繰り返します。
先頭の要素を取得する(findFirst)
List<String> c1 = new ArrayList<>(Arrays.asList("赤", "黄", "青"));
Optional list2 = c1.stream().findFirst();
System.out.println(list2.get()); //赤
findFirstメソッドで先頭の要素を取得します。
リストを返す(collect+toList)
List<String> c1 = new ArrayList<>(Arrays.asList("aa", "ab", "ac"));
List list2 = c1.stream()
.map(a -> a + "です")
.collect(Collectors.toList());
System.out.println(list2); //[aaです, abです, acです]
collect+toListでリストを返します。
要素の条件が全て一致するか(allMatch)
List<Integer> num1 = new ArrayList<>(Arrays.asList(5,8,9));
boolean a = num1.stream()
.allMatch(b -> b > 7); //すべての要素は7より大きいか
System.out.println(a); //false
boolean c = num1.stream()
.allMatch(d -> d > 3); //すべての要素は3より大きいか
System.out.println(c); //true
すべての要素の条件が一致した場合はtrueをそうでない場合はfalseを返します。
要素の条件が1つでも一致するか(anyMatch)
List<Integer> num1 = new ArrayList<>(Arrays.asList(5,8,9));
boolean a = num1.stream()
.anyMatch(b -> b > 10); //10より大きい要素はあるか
System.out.println(a); //false
boolean c = num1.stream()
.anyMatch(d -> d > 8); //8より大きい要素はあるか
System.out.println(c); //true
要素の条件が1つでも一致した場合はtrueをそうでない場合はfalseを返します。
要素の条件が一致するものは1つもないか(noneMatch)
List<Integer> num1 = new ArrayList<>(Arrays.asList(5,8,9));
boolean a = num1.stream()
.noneMatch(b -> b > 7); //7より大きい要素はひとつもないか
System.out.println(a); //false
boolean c = num1.stream()
.noneMatch(d -> d > 10); //10より大きい要素はひとつもないか
System.out.println(c); //true
noneMatchメソッドは一致が1つもない場合にtrueを返します。
並列に処理する(parallelStream/parallel)
List<String> colors = new ArrayList<>(Arrays.asList("A","B","C","D"));
colors.parallelStream()
.map(a -> a + "です")
.forEach(System.out::println); //Cです Dです Aです Bです
colors.stream()
.parallel()
.map(a -> a + "です")
.forEach(System.out::println); //Cです Aです Bです Dです
parallelStreamとparallelは、要素が並列に処理されるので返される値の順番は決まっていません。
配列でストリームを使用する
- 配列でStreamのインスタンスを生成するにはArraysクラスのstreamメソッドを使用します。
- Arraysクラスは、配列を操作するためのクラスです。
- 以下は、OracleのJava8のArraysクラスのstreamメソッドのリンクです。
https://docs.oracle.com/javase/jp/8/docs/api/java/util/Arrays.html#stream-T:A-
String[] arr = {"赤","黄","青"};
long a = Arrays.stream(arr).count();
System.out.println(a); // 3
countは、要素数を返します。
関連の記事
Java ラムダ式のサンプル
Java ラムダ式で関数型インターフェースを使用
Java Stream APIで数値を合計する(IntStream)