Javaでストリーム操作のグループ化を行う際に利用出来るのが「Collectors.groupingBy」です。
本記事では、Javaストリームでグループ化する方法について、サンプルコードを掲載しながらご紹介していきます。
目次
JavaのCollectorsとは

Javaでは、Java8以降Stream APIが利用出来るようになり、終端操作のひとつとしてCollectorsクラスが提供されています。
Stream API
Stream APIは、コレクションや配列といったデータを元に集計操作を実施出来るAPIです。
Java8以降のバージョンで利用出来るようになりました。
従来のコレクションに対して実施していた処理を、より簡潔に記述することが出来るようになります。
終端操作
CollectorsクラスはStream APIの「終端操作」にあたるクラスで、コレクションのデータに対して処理を適用する役目です。
これに対し「中間操作」と呼ばれるものは、コレクションから取得したデータを変換する処理のことを指しています。
Javaでグループ化を実施するCollectors.groupingbyの処理

Javaでグループ化を実施する場合、Collectors.groupingbyを利用すれば簡単に集約処理が実施出来ます。
サンプル
package sample;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List list = new ArrayList (Arrays.asList("あいうえお", "かきくけこ", "あかさたな", "わをん"));
Map<String, List> gMap = list.stream().collect(Collectors.groupingBy(s -> s.substring(0,1)));
System.out.println(gMap);
}
}
実行結果が下記です。
{あ=[あいうえお, あかさたな], か=[かきくけこ], わ=[わをん]}
解説
サンプルでは、14行目でstreamAPIを使用し、Collectors.groupingbyメソッドによりグループ化の処理を実施しています。
対象のリストは12行目で作成しているオブジェクトで、「s -> s.substring(0,1)」の部分が条件となり、意味合いとしてはリストの中で1桁目の頭文字が一致しているデータでグループ化を実施するという処理になります。
出力結果は頭文字が「あ」の文字列がグループ化されており、条件に沿ったキーでマッピングされていることをご確認頂けます。
グループ化の集約方法を変更するJavaサンプル

Collectors.groupingbyはデフォルトではリストとして集約しますが、SetやMapとして集約することも可能です。
サンプル
package sample;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
Student student1= new Student(21, "男", "たろう");
Student student2= new Student(18, "女", "あや");
Student student3= new Student(31, "女", "みき");
Student student4= new Student(45, "男", "こういち");
Student student5= new Student(30, "男", "まさき");
Student student6= new Student(23, "男", "しょうへい");
Student student7= new Student(19, "男", "けん");
Student student8= new Student(41, "男", "ゆきひろ");
Student student9= new Student(36, "女", "みさと");
Student student10= new Student(26, "女", "あゆみ");
Stream studentStream = Stream.of(student1, student2, student3, student4, student5,
student6, student7, student8, student9, student10);
Map<Object, Set> sMap = studentStream.map(s -> s.age).collect(Collectors.groupingBy(s -> (s / 10) * 10, Collectors.toSet()));
System.out.println(sMap);
}
}
class Student {
public int age;
public String sex;
public String name;
public Student(int age, String sex, String name) {
this.age = age;
this.sex = sex;
this.name = name;
}
}
実行結果が下記です。
{20=[21, 23, 26], 40=[41, 45], 10=[18, 19], 30=[36, 30, 31]}
解説
サンプルでは「Student」クラスに対して、ストリームで年代別にSet形式で値を取得しているサンプルです。
11~20行目はStudentクラスのインスタンスを生成している処理で、作成された全てのインスタンスを22行目でストリームとして読み込みます。
25行目の処理では「Collectors.toSet())」を明示することでSet形式で取得するように設定しています。
「s -> (s / 10) * 10」の部分に関しては年代別で取得するための処理で、サンプル用の条件であるため、好きな条件を指定して問題ありません。
さいごに: JavaのCollectors.groupingByを使ってグループ化を試してみよう

本記事では、Java8以降で利用可能となったストリームの終端操作「Collectors.groupingBy」を使用したグループ化の方法についてご紹介してきました。
Java8以降のラムダ式での書き方などに慣れていない方には読みにくいコードに感じるかも知れませんが、少ない記述で集約処理を簡単に実施出来る便利なメソッドです。
まだJava8以降の記述法に慣れない方も少しずつ今回ご紹介したようなストリーム操作にチャレンジしてみてください。
Map形式で取得したい場合には、「Collectors.toMap()」が利用可能です。