英文:
JAVA List GroupBy multiple fields and Sum
问题
我有一个包含字段Name、Currency和Amount的列表。
我想按Name、Currency分组,并计算Amount的总和。
我希望结果/输出是一个列表。
英文:
I have list having fields Name, Currency and Amount.
I want to group it by Name, Currency and Sum of Amount.
List<myPojo> rows= ................
public class myPojo
{
private String name;
private String currency;
private BigDecimal amount;
......................
}
I want result/output in list
答案1
得分: 2
你可以使用流API。
使用Collectors.toMap
,并使用AbstractMap.SimpleEntry
作为地图的键。然后为相同键的多个值定义合并函数。
List<myPojo> res = new ArrayList<>(rows.stream()
.collect(Collectors.toMap(
e -> new AbstractMap.SimpleEntry<>(e.getName(), e.getCurrency()),
Function.identity(),
(a, b) -> new myPojo(a.getName(), a.getCurrency(), a.getAmount().add(b.getAmount()))))
.values());
演示:
List<myPojo> list = new ArrayList<>();
list.add(new myPojo("A", "USD", new BigDecimal(1.0)));
list.add(new myPojo("A", "USD", new BigDecimal(2.0)));
list.add(new myPojo("A", "USD", new BigDecimal(3.0)));
list.add(new myPojo("B", "USD", new BigDecimal(1.0)));
list.add(new myPojo("B", "USD", new BigDecimal(2.0)));
list.add(new myPojo("B", "USD", new BigDecimal(3.0)));
list.add(new myPojo("A", "US", new BigDecimal(1.0)));
list.add(new myPojo("A", "US", new BigDecimal(2.0)));
list.add(new myPojo("A", "US", new BigDecimal(3.0)));
List<myPojo> res = new ArrayList<>(list.stream()
.collect(Collectors.toMap(
e -> new AbstractMap.SimpleEntry<>(e.getName(), e.getCurrency()),
Function.identity(),
(a, b) -> new myPojo(a.getName(), a.getCurrency(), a.getAmount().add(b.getAmount()))))
.values());
System.out.println(res.toString());
输出:
[myPojo [name=B, currency=USD, amount=6],
myPojo [name=A, currency=USD, amount=6],
myPojo [name=A, currency=US, amount=6]]
注意: 为了更好的约定,尝试将类的名称大写,如MyPojo
。
英文:
You can use Stream API.
Use Collectors.toMap
and use AbstractMap.SimpleEntry
as key of map. Then define merge function for multiple values of the same key.
List<myPojo> res = new ArrayList<>(rows.stream()
.collect(Collectors.toMap(
e -> new AbstractMap.SimpleEntry<>(e.getName(), e.getCurrency()),
Function.identity(),
(a, b) -> new myPojo(a.getName(), a.getCurrency(), a.getAmount().add(b.getAmount()))))
.values());
Demo:
List<myPojo> list = new ArrayList<>();
list.add(new myPojo("A", "USD", new BigDecimal(1.0)));
list.add(new myPojo("A", "USD", new BigDecimal(2.0)));
list.add(new myPojo("A", "USD", new BigDecimal(3.0)));
list.add(new myPojo("B", "USD", new BigDecimal(1.0)));
list.add(new myPojo("B", "USD", new BigDecimal(2.0)));
list.add(new myPojo("B", "USD", new BigDecimal(3.0)));
list.add(new myPojo("A", "US", new BigDecimal(1.0)));
list.add(new myPojo("A", "US", new BigDecimal(2.0)));
list.add(new myPojo("A", "US", new BigDecimal(3.0)));
List<myPojo> res = new ArrayList<>(list.stream()
.collect(Collectors.toMap(
e -> new AbstractMap.SimpleEntry<>(e.getName(), e.getCurrency()),
Function.identity(),
(a, b) -> new myPojo(a.getName(), a.getCurrency(), a.getAmount().add(b.getAmount()))))
.values());
System.out.println(res.toString());
Output:
[myPojo [name=B, currency=USD, amount=6],
myPojo [name=A, currency=USD, amount=6],
myPojo [name=A, currency=US, amount=6]]
Note: Try to capitalize the name of the class like MyPojo
for better convention
答案2
得分: 1
您可以使用groupingBy来生成一个Map<String,Map<String,BigDecimal>>
,对应于Map<Name,Map<Currency,sum of Amount>>
List<myPojo> rows = List.of(new myPojo("ABCD", "USD", new BigDecimal(20)),
new myPojo("XYZ", "GBP", new BigDecimal(60)),
new myPojo("XYZ", "THB", new BigDecimal(35)),
new myPojo("ABCD", "INR", new BigDecimal(90)),
new myPojo("ABCD", "USD", new BigDecimal(80)),
new myPojo("XYZ", "THB", new BigDecimal(45)));
Map<String,Map<String,BigDecimal>> map =
rows.stream()
.collect(Collectors.groupingBy(myPojo::getName,
Collectors.groupingBy(myPojo::getCurrency,
Collectors.reducing(BigDecimal.ZERO, myPojo::getAmount, BigDecimal::add))));
System.out.println(map);
// 输出: {XYZ={GBP=60, THB=80}, ABCD={USD=100, INR=90}}
希望这个帮助!
英文:
You could use groupingBy to generate a Map<String,Map<String,BigDecimal>>
corresponding to Map<Name,Map<Currency,sum of Amount>>
List<myPojo> rows = List.of(new myPojo("ABCD", "USD", new BigDecimal(20)),
new myPojo("XYZ", "GBP", new BigDecimal(60)),
new myPojo("XYZ", "THB", new BigDecimal(35)),
new myPojo("ABCD", "INR", new BigDecimal(90)),
new myPojo("ABCD", "USD", new BigDecimal(80)),
new myPojo("XYZ", "THB", new BigDecimal(45)));
Map<String,Map<String,BigDecimal>> map =
rows.stream()
.collect(Collectors.groupingBy(myPojo::getName,
Collectors.groupingBy(myPojo::getCurrency,
Collectors.reducing(BigDecimal.ZERO, myPojo::getAmount, BigDecimal::add))));
System.out.println(map);
// output: {XYZ={GBP=60, THB=80}, ABCD={USD=100, INR=90}}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论