0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaのStreamAPIでソートとgroup byのようなことをする

Posted at

SQLではよくやりますが、Java側でソートとGROUP BYを行うことがあったので書き留めておきます。

ソート

list.stream()
.sorted(Comparator.comparing(TestClass::getId)
.thenComparing(TestClass::getName)
.collect(Collectors.toList())

やっていることは
1,listをstreamに渡し、TestClass.getIdで比較します。
2,1で比較して同じ順位だった場合、TestClass::getNameで比較します。
3,listに戻して返します。

SQLでいうと

ORDER BY ID,NAME

のようなイメージです。

group by

list.stream()
.collect(
    Collectors.groupingBy(
    TestClass::getId, 
    Collectors.groupingBy(TestClass::getName)
    )
)
.collect(Collectors.toList())

やっていることは
1,listをstreamに渡し、TestClass.getIdでグルーピングします。
2,1で集計した後、TestClass::getNameでグルーピングします。
3,listに戻して返します。

SQLでいうと

GROUP BY ID,NAME

のようなイメージです。

番外編

検索してもなかなかやり方が見つからず苦労したので、記載しておきます。
1:Nの関係のデータにおいて以下のようなMapを作りたい時があります。

Map<String, List<Int>>

これを実現するには上記のgroupingbyと同時に、Collectors.mappingを使用します。
以下の通りTestObjectがあるとして、

// 伝票番号と明細番号を持つだけのクラスです
public class TestObject {

    private String slipNo;
    private int detailNo;

    public SlipDetail(String slipNo, int detailNo) {
        this.slipNo = slipNo;
        this.detailNo = detailNo;
    }

    public String getSlipNo() {
        return slipNo;
    }

    public int getDetailNo() {
        return detailNo;
    }

    public void setSlipNo(String slipNo) {
        this.slipNo = slipNo;
    }

    public void setDetailNo(int detailNo) {
        this.detailNo = detailNo;
    }
}

このクラスのデータを持つListが以下のイメージであるとします。

// 同一の伝票番号に複数の明細番号が紐づくデータがいくつかある状態
List<TestObject> testObjectList =
{{1000,1},{1000,2},{1001,1},{1001,2},{1002,1}}

これらを{伝票番号、明細番号のリスト}のようにMap化すると

Map<String,List<Int>> testObjectMap =
testObjectList
.stream()
.collect(
    Collectors.groupingBy(
        test -> test.getSlipNo(),
        Collectors.mapping(
            test -> test.getDetailNo, 
            Collectors.toList()
        )
    )
)

// 上記で作成されるtestObjectMapの中身
// {{1000,{1,2}},{1001,{1,2}},{1002,{1}}}

やっていることは
1,listをstreamに渡し、TestObject.getSlipNoでグルーピングします。
2,1で集計したグループに対して、
さらにTestObject.getDetailNoで明細番号を取り出し、それらをListにします。

ご指摘などあればお待ちしております!

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?