javaで複数の変数でgroup byをして、マージされた数値型のデータをsumし、list型にしてデータを抽出したいです。
短く綺麗に書ける方法があれば教えていただきたいです。
-Item class
Java
1import lombok.AllArgsConstructor; 2import lombok.Data; 3 4@Data 5@AllArgsConstructor 6public class Item { 7 private String orderId; 8 private String itemId; 9 private String itemName; 10 private String itemGenre; 11 private Integer number; 12 13}
以下のデータを用意した時、
java
1final ArrayList<Item> items = new ArrayList<>(); 2 items.add(new Item("00-82-947", "8810", "item name1", "01", 1)); 3 items.add(new Item("00-82-952", "8810", "item name1", "01", 2)); 4 items.add(new Item("00-91-135", "8315", "item name2", "02", 3)); 5 items.add(new Item("00-91-140", "8315", "item name3", "02", 4)); 6 7 // TODO データ抽出処理...(itemId, itemName, itemGenreが同じデータがある場合、numberを合計してマージする) 8 // list型 9 System.out.println(items);
以下の結果になるようにデータを抽出したいです。
orderIdが"00-82-952"と"00-82-947"のデータはitemId, itemName, itemGenreが同じなのでgroup byされ、numberがsumされ3(=1+2)になります。またSQLでgroup byするときと同じように、key(ここではorderId)が小さい方を残したいです。この例だとorderIdが"00-82-952"と"00-82-947"のデータレコードがgroup byされて、"00-82-947"が残ります。
java
1[Item(orderId=00-82-947, itemId=8810, itemName=item name1, itemGenre=01, number=3), 2Item(orderId=00-91-135, itemId=8315, itemName=item name2, itemGenre=02, number=3), 3Item(orderId=00-91-140, itemId=8315, itemName=item name3, itemGenre=02, number=4)]
やりたいことはSQLで表現すると以下になります。
SQL
1select orderId, itemId, itemName, itemGenre, sum(number) as number 2from item 3group by itemId, itemName, itemGenre;
調べたところ以下の方法のようにDtoにequalsとhasCodeをオーバーライドしてgroup byしたい変数を追加すれば実現できますが、
これだとgroup by以外の変数がnullになってしまい(今回だとorderId)、orderIdをsetする処理を書く必要があります。
http://codestudyblog.com/questions/sf/0421195604.html
java
1users.stream() 2.collect(Collectors 3.groupingBy(user -> new User(user.name, user.phone, user.address), 4 Collectors.summarizingLong(user -> user.scope)) 5 ).forEach((k,v) -> { 6 k.scope = v.getSum(); 7 System.out.println(k); 8 });
また以下のようにCollectors.groupingByを使ってMapにすることで実現できそうですが、今回はgroup byの条件が3項目なので、Mapが3つできてしまい、listにするのにコードが長くなってしまいます。
https://stackoverflow.com/questions/28342814/group-by-multiple-field-names-in-java-8
Java
1Map<String, Map<Integer, List<Person>>> map = people 2 .collect(Collectors.groupingBy(Person::getName, 3 Collectors.groupingBy(Person::getAge));
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/09/11 10:45
2021/09/11 12:08
2021/09/11 14:29