当サイトは、アフィリエイト広告を利用しています
Collectors.groupingByを使うと指定した条件にしたがって配列やListを
2つに分割してMap<boolean,List< T >>のMap型データを取得できる
※Tは分割対象のオブジェクト。
似たようなことができる「groupingby」メソッドもある。
groupingbyメソッドはpartitioningByメソッドの上位互換的なもので
Listを2分割ではなく、groupに分割できる
groupingbyメソッドについては下記記事で紹介しています。
下記の本では streamAPI についても詳しく書いてありおススメです!
また当ブログで紹介しているjava8のstreamAPIを使った
コレクションや配列の操作方法を
下記記事でメソッド別にまとめています!
Collectors.partitioningByは引数の数が1~2つの場合がある。
Map<boolean,List< T >> partitioningBy(Predicate<? super T> predicate)
Map<K,D> partitioningBy(Predicate<? super T> predicate,Collector<? super T,A,D> downstream)
引数一つの場合は戻り値はMap<boolean,List< T >>固定だが
第二引数の関数で変換してやることで
など、分割した結果の型を変えることができる。
Personクラスを使う
public class Person {private final int id;private final String name;private final String address;private final int age;Person(int id,String name, String address,int age) {this.id = id;this.name = name;this.address = address;this.age = age;}public int getId() {return this.id;}public String getName() {return this.name;}public String getAddress() {return this.address;}public int getAge() {return this.age;}@Overridepublic String toString(){return "{" + this.id + " " + this.name + " " + this.address + this.age +"}";}}
partitioningByに引数を一つだけ設定した場合
その引数を分割関数で分割したMap<boolean,List< T >>で値を取得できる。
import java.util.*;import java.util.stream.Collectors;public class Main {public static void main(String[] args) throws Exception {// PersonのListを作成List<Person> personlist = Arrays.asList(new Person(1,"TANAKA","東京",11),new Person(1,"YOSHIDA","青森",21),new Person(2,"YAMADA","山梨",23),new Person(3,"OOTANI","熊本",45),new Person(3,"TUJIMURA","京都",80),new Person(3,"MURATA","熊本",22),new Person(4,"OKAMOTO","大阪",2),new Person(4,"MORITA","滋賀",54),new Person(4,"KAWASAKI","滋賀",78));// 分割Map<Boolean, List<Person>> map =personlist.stream().collect(Collectors.partitioningBy(person -> person.getId()>2 //分割条件));System.out.println(map);}}// 実行結果// {// false=[// {1 TANAKA 東京11},// {1 YOSHIDA 青森21},// {2 YAMADA 山梨23}// ],// true=[// {3 OOTANI 熊本45},// {3 TUJIMURA 京都80},// {3 MURATA 熊本22},// {4 OKAMOTO 大阪2},// {4 MORITA 滋賀54},// {4 KAWASAKI 滋賀78}// ]// }
指定した分割条件で分割されている
引数を2つにして分割結果をList< T >以外の型で受け取る
Map<boolean,List< T >>のList< T >の部分をMapで受け取る
import java.util.*;import java.util.stream.Collectors;public class Main {public static void main(String[] args) throws Exception {// PersonのListを作成List<Person> personlist = Arrays.asList(new Person(1,"TANAKA","東京",11),new Person(1,"YOSHIDA","青森",21),new Person(2,"YAMADA","山梨",23),new Person(3,"OOTANI","熊本",45),new Person(3,"TUJIMURA","京都",80),new Person(3,"MURATA","熊本",22),new Person(4,"OKAMOTO","大阪",2),new Person(4,"MORITA","滋賀",54),new Person(4,"KAWASAKI","滋賀",78));// 分割// 結果をMap<Integer,String>で取得するMap<Boolean, Map<Integer,String>> map =personlist.stream().collect(Collectors.partitioningBy(person -> person.getId()>2, //分割条件Collectors.toMap( //集約結果のMapを作成e->e.getId(), // キーはIde->e.getName(), // バリューはname(oldVal,newVal) -> newVal) // 後勝ち));System.out.println(map);}}// 実行結果// {false={1=YOSHIDA, 2=YAMADA}, true={3=MURATA, 4=KAWASAKI}}
分割結果がMapで取得できている。
Mapにキーが重複しているため後勝ちになっている
Map<K,List< T >>のList< T >の部分を任意のListで受け取る
このサンプルではPerson.ageのListで受け取るようにする。
import java.util.*;import java.util.stream.Collectors;public class Main {public static void main(String[] args) throws Exception {// PersonのListを作成List<Person> personlist = Arrays.asList(new Person(1,"TANAKA","東京",11),new Person(1,"YOSHIDA","青森",21),new Person(2,"YAMADA","山梨",23),new Person(3,"OOTANI","熊本",45),new Person(3,"TUJIMURA","京都",80),new Person(3,"MURATA","熊本",22),new Person(4,"OKAMOTO","大阪",2),new Person(4,"MORITA","滋賀",54),new Person(4,"KAWASAKI","滋賀",78));// 分割// 結果をMap<Integer,String>で取得するMap<Boolean, List<Integer>> map =personlist.stream().collect(Collectors.partitioningBy(person -> person.getId()>2, //分割条件Collectors.mapping( //分割結果をmappingするPerson::getAge, // ageをまとめてListにするCollectors.toList())));System.out.println(map);}}// 実行結果// {false=[11, 21, 23], true=[45, 80, 22, 2, 54, 78]}
分割条件キーごとにageのListが取得できる。
他にもpartitioningBy後に編集できるCollectorsのサンプルをのせる
分割条件で分割してからに分割ごとのageの合計を出す
import java.util.*;import java.util.stream.Collectors;public class Main {public static void main(String[] args) throws Exception {// PersonのListを作成List<Person> personlist = Arrays.asList(new Person(1,"TANAKA","東京",11),new Person(1,"YOSHIDA","青森",21),new Person(2,"YAMADA","山梨",23),new Person(3,"OOTANI","熊本",45),new Person(3,"TUJIMURA","京都",80),new Person(3,"MURATA","熊本",22),new Person(4,"OKAMOTO","大阪",2),new Person(4,"MORITA","滋賀",54),new Person(4,"KAWASAKI","滋賀",78));// 分割// 分割後にageを合計するMap<Boolean, Integer> map =personlist.stream().collect(Collectors.partitioningBy(person -> person.getId()>2, //分割条件Collectors.reducing(0,//初期値Person::getAge, // 集計する対象(accum, value)-> accum + value //集計関数)));System.out.println(map);}}// 実行結果// {false=55, true=281}
分割ごとにageが合計されている。
分割条件で分割後してから分割ごとに最小のageを返却する
import java.util.*;import java.util.stream.Collectors;public class Main {public static void main(String[] args) throws Exception {// PersonのListを作成List<Person> personlist = Arrays.asList(new Person(1,"TANAKA","東京",11),new Person(1,"YOSHIDA","青森",21),new Person(2,"YAMADA","山梨",23),new Person(3,"OOTANI","熊本",45),new Person(3,"TUJIMURA","京都",80),new Person(3,"MURATA","熊本",22),new Person(4,"OKAMOTO","大阪",2),new Person(4,"MORITA","滋賀",54),new Person(4,"KAWASAKI","滋賀",78));// 分割// 分割後にageを合計するMap<Boolean, Optional<Person>> map =personlist.stream().collect(Collectors.partitioningBy(person -> person.getId()>2, //分割条件Collectors.minBy(Comparator.comparing(Person::getAge))));System.out.println(map);}}// 実行結果// {false=Optional[{1 TANAKA 東京11}], true=Optional[{4 OKAMOTO 大阪2}]}
基本的にgroupingByとほぼ一緒だった。
恐れらくpartitioningByでできることはgroupingByでもできると思われる。
※使いどころを考える必要がありそう
下記の本ではstreamAPIについても詳しく書いてありおススメです!