Lambda式のcollect

3309 ワード

詳細
本文はcollectの高度な使い方を記録する.
 
テストデータの準備
 
class Item implements Comparable {
    public String id;
    public int count;

    public Item(String id, int count) {
        this.id = id;
        this.count = count;
    }

    @Override
    public int compareTo(Item o) {
        return count - o.count;
    }

    @Override
    public String toString() {
        return String.format("(%s, %d)", id, count);
    }
}

 
 
 
Item item1 = new Item("it1", 1);
Item item2 = new Item("it2", 3);
Item item3 = new Item("it3", 2);
Item item4 = new Item("it4", -1);

List list = new ArrayList<>();
list.add(item1);
list.add(item2);
list.add(item3);
list.add(item4);

 
 
1.他のタイプの集合に変換
例えばtoSet()toList()は、具体的なタイプを限定してもよい.
 
Set set = list.stream().collect(Collectors.toCollection(TreeSet::new));

ItemがComparableを実装していない場合、refer Using streams to collect into TreeSet with custom comparator
 
 
2.valueに変換
例えばminBy,maxBy,averagingIntなど
 
Optional res = list.stream()
	.collect(Collectors.minBy(
				Comparator.comparingInt(item -> item.count)));

 
double aver = list.stream().collect(Collectors.averagingInt(item -> item.count));

 
 
stringタイプの場合はjoinで接続できます
 
String join = list.stream()
	.map(item -> item.id)
	.collect(Collectors.joining(",", "[", "]"));
//  [it1,it2,it3,it4]

 
 
3.分割--判断結果によって2つのグループに分ける
 
Map> map = list.stream()
		.collect(Collectors.partitioningBy(item -> item.count > 1));
// {false=[(it1, 1), (it4, -1)], true=[(it2, 3), (it3, 2)]}

 
 
4.グループ--SQLのgroupbyと似ています
分割機能を実現し、効果を強調するためにitem 2のcount値を2に設定し、countに従ってグループ化することができます.
Map> map = list.stream()
		.collect(Collectors.groupingBy(item -> item.count));
// {-1=[(it4, -1)], 1=[(it1, 1)], 2=[(it2, 2), (it3, 2)]}

 
5.組み合わせて使用
比較的多いgroupingByでの使用
例えばcountの同じitemの個数を求めます
Map countMap = list.stream()
		.collect(Collectors.groupingBy(
					item -> item.count, Collectors.counting()));
// {-1=1, 1=1, 2=2}

 
たとえばcountでグループ化すると、結果は文字列で接続されます.
Map strMap = list.stream()
        .collect(Collectors.groupingBy(
                item -> item.count,
                Collectors.mapping(it -> it.id,
                        Collectors.joining(",", "[", "]"))));
// {-1=[it4], 1=[it1], 2=[it2,it3]}

実はグループ化が完了した後、リストごとに二次操作を行います.
 
カスタムcollectorの話題については、こちらはcoverではありません.