- 開発技術
JavaのStream APIについて
- #Java
Stream APIとは
【エンジニア募集中】フルリモート可◎、売上/従業員数9年連続UP、平均残業8時間、有給取得率90%、年休124日以上 etc. 詳細はこちらから>
Collectionや配列を扱うAPIです。
List等の集計やソートを行うときに、for文を書かなくても、わかりやすく簡潔なソースコードを書くことができます。
Collection型(ListやSet)ではStreamを取得でき、取得したStreamから中間操作や終端操作のメソッドを呼び出します。
今回は自身がよく使った中間操作と終端操作をご紹介します。
中間操作
filter
条件に一致した値で絞り込むことができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
List<Integer> testInt = new ArrayList<Integer>(); testInt.add(1); testInt.add(2); testInt.add(3); testInt.add(4); testInt.add(5); // 3以上の数値に絞り込む testInt.stream() .filter(num -> num >= 3) // 中間操作 .forEach(System.out::println); // 終端操作 // 「3」「4」「5」が出力される |
ちなみに、filterを二つ付けるとAND条件で絞り込みが可能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
List<Integer> testInt = new ArrayList<Integer>(); testInt.add(1); testInt.add(2); testInt.add(3); testInt.add(4); testInt.add(5); // 2~4に絞り込み testInt.stream() .filter(num -> num >= 2) // 中間操作 .filter(num -> num <= 4) // 中間操作 .forEach(System.out::println); // 終端操作 // 「2」「3」「4」が出力される |
map
要素を取得することができるので、各値の変換等が可能です。
1 2 3 4 5 6 7 8 9 10 |
List<String> testStr = new ArrayList<String>(Arrays.asList("1", "2", "3")); // 文字列→数値に変換 int sum = testStr.stream() .map((String x) -> Integer.valueOf(x)) // 中間操作 .collect(Collectors.summingInt(Integer::intValue)); // 終端操作 System.out.println(sum); // 「6」が出力される |
sorted
値のソートが可能です。
ComparableやComparatorインタフェースを実装して、compareToやcompareメソッドのオーバーライドで比較メソッドを使うことも可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// sortedで昇順に並び替え List<Integer> sortedTest = new ArrayList<Integer>(Arrays.asList(30, 100, 50, 120, 15); System.out.println(Arrays.toString( sortedTest.stream() .sorted() .toArray())); // [15, 30, 50, 100, 120]が出力される // sortedとjava.util.Comparatorを使用して降順で並び替え List<Integer> sortedTest2 = new ArrayList<Integer>(Arrays.asList(30, 100, 50, 120, 15)); System.out.println(Arrays.toString( sortedTest2.stream() .sorted(Comparator.reverseOrder()) .toArray())); // [120, 100, 50, 30, 15]が出力される |
終端操作
forEach
要素を順に処理します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
public static class CustomerInfo { CustomerInfo() {} CustomerInfo(String name, String address, String telNo) { this.name = name; this.address = address; this.telNo = telNo; } private String name; // 氏名 private String address; // 住所 private String telNo; // 電話番号 public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getTelNo() { return telNo; } public void setTelNo(String telNo) { this.telNo = telNo; } @Override public String toString() { return "name=" + this.getName() + ", address=" + this.getAddress() + ", telNo=" + this.getTelNo(); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// forEachで値の上書き List<CustomerInfo> infoList = new ArrayList<CustomerInfo>(); infoList.add(new CustomerInfo("田中", "東京", "00011112222")); infoList.add(new CustomerInfo("伊藤", "愛知", "33344445555")); infoList.add(new CustomerInfo("山田", "愛知", "66677778888")); infoList.stream().forEach(item -> { item.setTelNo("99999999999"); }); infoList.stream().forEach(item -> System.out.println(item.toString())); // name=田中, address=東京, telNo=99999999999 // name=伊藤, address=愛知, telNo=99999999999 // name=山田, address=愛知, telNo=99999999999 が出力される |
collect
各要素をCollectionなどに収集します。
例ではListとしてまとめる処理を記載しました。
1 2 3 4 5 6 7 8 9 10 |
List<String> testCollect = new ArrayList<String>(Arrays.asList("aab", "ccc", "bbb", "acd", "baa")); // bを含むもののみ絞り込んでListに収集 List<String> result = testCollect.stream() .filter(x -> x.contains("b")) // 中間操作 .collect(Collectors.toList()); // 終端操作 System.out.println(Arrays.toString(result.toArray())); // [aab, bbb, baa]が出力される |
ご紹介したstreamメソッド以外にも便利なStream APIがあるので、自分の用途にあったものを探すのも良いかと思います。
可読性があがるのがメリットではありますが、多用のし過ぎは逆に可読性が低くなる可能性もあるため、使い方は要注意です。
参照:javadoc
https://docs.oracle.com/javase/jp/8/docs/api/java/util/stream/Stream.html
【エンジニア募集中】フルリモートも◎(リモート率85.7%)、平均残業8時間、年休124日以上、有給取得率90% etc. 詳細はこちらから>