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にします。
ご指摘などあればお待ちしております!
参考