#目的
Java言語を含めたプログラミングの学習を始めたばかりの方、既学習者の方は復習用に、
今回はStream APIについて学ぶために書いています。
【Java入門目次】
・変数と型
・型変換
・変数のスコープ
・文字列の操作
・配列の操作
・演算子
・条件分岐
・繰り返し処理
・クラスについて(準備中)
・抽象クラス(準備中)
・インターフェース(準備中)
・カプセル化(準備中)
・モジュールについて(準備中)
・例外処理について
・ラムダ式について
・Stream APIについて ←今ここ
#Stream APIとは
Java8から導入された機能で、コレクションの要素に対する操作が可能なAPIです。
コレクションをStream化→中間操作(データを加工)→終端操作(加工したデータを得る)
という処理の流れになります。
Stream APIの中間操作は複数記述することが可能なので、複雑そうに見える処理もスッキリと記述することが出来ます。
各メソッドの引数に関数型インターフェースを受け取る場合もあり、そこでラムダ式を用いていますがそこの説明は割愛します。
**ラムダ式について**をご覧ください。
#Stream APIの例
実際にどの様に扱うのか簡単な例で比較します。
まずは、Stream APIを使わず実装。
List<String> names = Arrays.asList("大瀬良", "佐村河内", "菊池", "畝", "長野", "城之内");
for (int i = 0; i < names.size(); i++) {
if (names.get(i).length() >= 3) {
if (names.get(i).contains("内")) {
System.out.println(names.get(i)); // 佐村河内 城之内
}
}
}
次に、Stream APIを使って
同様の処理を実装します。
List<String> names = Arrays.asList("大瀬良", "佐村河内", "菊池", "畝", "長野", "城之内");
names.stream()
.filter(name -> name.length() >= 3)
.filter(name -> name.contains("内"))
.forEach(name -> System.out.println(name)); // 佐村河内 城之内
ネストが深くならず読みやすくなり、シンプルに実装出来ていますね。
中間操作のfilterメソッドで条件を満たす要素のみを抽出し、
終端操作のforEachメソッドで1つずつ要素を出力しています。
#中間操作の紹介
先程は中間操作のメソッドとしてfilterを紹介しましたが、その他のメソッドもいくつか紹介していきます。
###1.map
各要素に指定した処理を行うメソッドです。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.stream()
.map(num -> num * 2) // 各要素を2倍にする
.forEach(num -> System.out.print(num + " ")); // 2 4 6 8 10
###2.limit
指定した要素数(maxSize個)だけを返してくれるメソッドです。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.stream()
.limit(3) // 3個だけ取り出す
.forEach(num -> System.out.print(num + " ")); // 1 2 3
###3.distinct
重複を除いた要素を返してくれるメソッドです。
List<String> names = Arrays.asList("久保", "遠藤", "巻", "久保", "岡崎", "本田", "巻", "遠藤");
names.stream()
.distinct() // 重複した要素は取り除いて返す
.forEach(name -> System.out.print(name + " ")); // 久保 遠藤 巻 岡崎 本田
###4.sorted
要素を並び替えてくれるメソッドです。
List<Integer> numbers = Arrays.asList(1, 5, 3, 2, 4);
numbers.stream()
.sorted() // 昇順に並び替え
.forEach(num -> System.out.print(num + " ")); // 1 2 3 4 5
sortedメソッドの引数にComparatorインターフェースのreverseOrderメソッドを渡すことで、降順に並び替えることも出来ます。
List<Integer> numbers = Arrays.asList(1, 5, 3, 2, 4);
numbers.stream()
.sorted(Comparator.reverseOrder()) // 降順に並び替え
.forEach(num -> System.out.print(num + " ")); // 5 4 3 2 1
#終端操作の紹介
これまでは終端操作のメソッドとしてforEachメソッドを用いていましたが、その他のメソッドもいくつか紹介していきます。
###1.anyMatch
条件によってbooleanを返すメソッドです。
要素の中に1つでも条件に合致する値があればtrueを返します。(一部一致判定)
List<String> fruits = Arrays.asList("banana", "apple", "orange", "pineapple");
boolean result = fruits.stream()
.anyMatch(fruit -> fruit.length() >= 7); // 7文字以上の文字数の要素はあるか判定
System.out.println(result); // true
###2.allMatch
条件によってbooleanを返すメソッドです。
要素全てが条件に合致していればtrueを返します。(全部一致合致)
List<Integer> numbers = Arrays.asList(2, 4, 6, 7, 8, 10);
boolean result = numbers.stream()
.allMatch(num -> num % 2 == 0); // 要素全てが偶数であるかを判定している
System.out.println(result); // false
###3.noneMatch
条件によってbooleanを返すメソッドです。
要素の中に1つでも条件に合致するもがあればfalseを返します。(全て非合致判定)
List<String> names = Arrays.asList("鈴木", "松井", "野茂", "井川", "川崎", "新庄", "ダルビッシュ有");
boolean result = names.stream()
.noneMatch(name -> name.length() > 4); // 4文字以上の文字数の要素はあるか判定
System.out.println(result); // false
#終わりに
コレクション要素に対しての操作を自分でダラダラと書くより、Stream APIを用いる事でソースコードがシンプルで読みやすくなるという事が分かりました。
最初は戸惑うかもしれませんが、ラムダ式と一緒にしっかりと覚えておきたいですね。
#参考サイト