前回の記事では、Java APIについて紹介しました。
本記事では、ラムダ式とStream APIについて紹介します。
ラムダ式とは
ラムダ式とは、Java 8から追加された新しい文法で、関数型プログラミングの概念を取り入れ、匿名関数を簡潔に表現する方法を提供します。
ラムダ式は次のような構文で記述します。
(型1 引数名1, 型2 引数名2, ....) -> {
....ラムダ式本体の処理....
}

何を書いているのかわからない...
ラムダ式を使う理由は以下です。
- 記述を簡潔にできる
- ラムダ式を前提に用意されたStream APIが使える

「Stream API」は非常に便利なAPIなので、使い方を覚えておきましょう。
これまでfor文でループしていた処理を簡潔に記述できます。
Stream APIとは
Stream APIとは、関数型プログラミング用のライブラリで、データを流し込み簡単に加工できるようになっています。
Java8から追加されたAPIで、今までコレクションに対して行っていた煩雑な処理を簡潔なコードで記述することが可能になりました。
次の例は、Stream APIを使い、次の条件に一致する人物をコンソールに出力しています。
- 30歳以上の人物
- 「order」の昇順に並び替える
- コンソールに出力するのは「name」だけ
import java.util.List;
public class StreamApiSample {
public record Names(String name, int age, int order) {
}
public static void main(String[] args) {
List<Names> list = List.of(
new Names("山田太郎", 66, 3),
new Names("山田次郎", 50, 1),
new Names("山田三郎", 33, 4),
new Names("山田四郎", 18, 2)
);
List<String> resultList = list.stream()
// 30歳以上の人物を抽出
.filter(n -> n.age >= 30)
// orderの昇順で並び変える
.sorted((s1, s2) -> s1.order-s2.order)
// nameのみ抽出する
.map(n -> n.name)
// Listに変換する
.toList();
resultList.forEach(System.out::println);
}
}
これまでは、for文等を使い対象レコードを抽出する必要がありましたが、Stream APIの登場により、上記例のように処理を簡潔に書けるようになりました。
主なStream APIの使い方は次のとおりです。
filter()
filterでは、データの中から指定した条件に一致するものを抽出します。
例えば、次のリストから「"い"」を含むデータだけを抽出するとします。
List<String> list = new ArrayList<String>();
list.add("にんじん");
list.add("じゃがいも");
list.add("きゃべつ");
list.add("さつまいも");
[Stream APIを使わない場合の例]
public class StreamApiSample {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("にんじん");
list.add("じゃがいも");
list.add("きゃべつ");
list.add("さつまいも");
// streamAPIを使わない場合
List<String> resultList = new ArrayList<String>();
for(String t : list) {
if (t.contains("い")) {
resultList.add(t);
}
}
}
}
[Stream APIを使う場合の例]
public class StreamApiSample {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("にんじん");
list.add("じゃがいも");
list.add("きゃべつ");
list.add("さつまいも");
// streamAPIを使った場合
List<String> resultList = list.stream().filter(t -> t.contains("い")).toList();
}
}
Stream APIを使わない場合は、for文で対象データを抽出する必要がありましたが、Stream APIを使う場合は、上記例のように簡潔に記述できます。
map()
mapは個々のデータを変換して、新しいデータを作ります。
次はmapの使用例です。リスト内の文字数を出力しています。
[mapの使用例]
public class StreamApiSample {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("test");
list.add("test123");
list.add("test12345");
// streamAPIを使った場合
list.stream().map(t -> t.length()).forEach(System.out::println);
}
}
[出力結果]
4
7
9
Stream APIのmap()で文字数に変換し、forEach(System.out::println)で文字数をコンソールに出力しています。
sorted()
sortedは、データを並び替えます。
次はsortedの使用例です。リスト内のデータを昇順に並び替えています。
[sortedの使用例]
public class StreamApiSample {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(23);
list.add(88);
list.add(10);
list.add(5);
// 昇順に並び替える
list.stream().sorted((s1, s2) -> s1-s2).forEach(System.out::println);
}
}
[出力結果]
5
10
23
88
Stream APIのsorted()で並び替えをおこない、forEach(System.out::println)で並び替えた結果をコンソールに出力しています。
reduce()
reduceは、データを1つずつ評価していき、結果に集約します。
次はreduceの使用例です。金額の合計を求めています。
[reduceの使用例]
public class StreamApiSample {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(10023);
list.add(1088);
list.add(2210);
list.add(25);
// streamAPIを使った場合
long sum = list.stream().reduce(0, (a,x) -> a+x);
System.out.println(sum);
}
}
[出力結果]
13346
Stream APIのreduce()で金額の合計を求め、System.out.printlnで結果をコンソールに出力しています。