☕️
StreamAPIでリストを分割する
やりたかったこと
- StreamAPIで、1つのリストを、条件次第で別々のリストに分けたい
- 命令的に書くなら、先に作ったArrayの中に
.add()
で詰め込んでいくだけなので簡単 - だが、Java8以降なのでStreamを使いたい
- 命令的に書くなら、先に作ったArrayの中に
- 条件による分類は1回で済ませたい
- 実際に使うときは複雑な条件を適用させる想定
- なので、同じリストに異なる条件を複数回適用してリスト生成、みたいなことはしたくなかった
実装
2種類に分割
Collectors.partitioningBy()
を使用する
2種類に分類
// 分類対象のIntegerリストを生成
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
// partitioningByを使って偶数奇数に分類したmapを生成する
Map<Boolean, List<Integer>> map = list.stream()
.collect(Collectors.partitioningBy(i -> i % 2 == 0));
// 偶数だけ取得
List<Integer> even = map.get(true);
System.out.println("even: " + even);
// 奇数だけ取得
List<Integer> odd = map.get(false);
System.out.println("odd: " + odd);
結果
even: [2, 4]
odd: [1, 3, 5]
- Collectors.partitioningBy()の条件次第で、trueのリストかfalseのリストのどちらかに入れるようにする
- それを
.get(bool)
で取り出す
3種類以上に分割
Collectors.groupingBy()
とenumを使う
3種類に分類
public class Main {
enum StartCategory {
STARTS_WITH_A, STARTS_WITH_B, OTHERS
}
public static void main(String[] args) {
List<String> words = Arrays.asList("Apple", "Banana", "Apricot", "Blueberry", "Cherry");
Map<StartCategory, List<String>> groupedByStart = words.stream()
.collect(Collectors.groupingBy(Main::getStartCategory));
List<String> startWithA = groupedByStart.get(StartCategory.STARTS_WITH_A);
System.out.println("Aで始まる: " + startWithA);
List<String> startWithB = groupedByStart.get(StartCategory.STARTS_WITH_B);
System.out.println("Bで始まる: " + startWithB);
List<String> others = groupedByStart.get(StartCategory.OTHERS);
System.out.println("その他: " + others);
}
private static StartCategory getStartCategory(String word) {
if (word.startsWith("A")) {
return StartCategory.STARTS_WITH_A;
} else if (word.startsWith("B")) {
return StartCategory.STARTS_WITH_B;
} else {
return StartCategory.OTHERS;
}
}
結果
Aで始まる: [Apple, Apricot]
Bで始まる: [Banana, Blueberry]
その他: [Cherry]
- enumを作って分類する
- それを
.get(enum)
で取り出す
Discussion