汇总列表<;X>;列出<;X>;使用Java8流API

汇总列表<;X>;列出<;X>;使用Java8流API,java,java-8,java-stream,Java,Java 8,Java Stream,我有以下课程: class Money { CurrencyUnit currencyUnit; BigDecimal amount; } 在我的应用程序中,我得到了一些随机的Money对象列表: currencyUnit | amount --------------------- EUR | 5.1 EUR | 0 USD | 1.09 EUR | 42 USD | 3 现在,我想使用Jav

我有以下课程:

class Money {
  CurrencyUnit currencyUnit;
  BigDecimal amount;
}
在我的应用程序中,我得到了一些随机的
Money
对象列表:

currencyUnit | amount
---------------------
EUR          | 5.1
EUR          | 0
USD          | 1.09
EUR          | 42
USD          | 3
现在,我想使用Java 8 Stream API创建以下结果(只需为每个currencyUnit的金额调用
BigDecimal::add
):

我已经知道/做过的事情:

Stream<Money> moneyStream = moneyList.stream();
但是我仍然需要遍历所有的键值对,并总结出数据量

做这件事的正确方法(可能是最简单的方法)是什么?不会那么复杂吧<代码>:)


编辑:如果不清楚我需要什么,下面是我的旧Java代码:

Map<CurrencyUnit, Money> map = new HashMap<>();
moneyList.stream().forEach(e -> {
    Money m = map.get(e.getCurrencyUnit());
    if(m == null) {
        m = new Money();
        m.setAmount(BigDecimal.ZERO);
        m.setCurrencyUnit(e.getCurrencyUnit());
        map.put(e.getCurrencyUnit(), m);
    }
    m.setAmount(m.getAmount().add(e.getAmount()));
});
return map.values();
Map Map=newhashmap();
moneyList.stream().forEach(e->{
Money m=map.get(如getCurrencyUnit());
如果(m==null){
m=新货币();
m、 设置金额(BigDecimal.ZERO);
m、 setCurrencyUnit(如getCurrencyUnit());
put(e.getCurrencyUnit(),m);
}
m、 setAmount(m.getAmount().add(e.getAmount());
});
返回map.values();

编辑2:另一个解决方案,它不是很优雅:

List<Money> list = inputList.stream()
    .collect(Collectors.groupingBy(Money::getCurrencyUnit))
    .values().stream().map(ml -> {
        Money money = new Money();
        ml.forEach(m -> {
            if(money.getCurrencyUnit() == null) {
                money.setCurrencyUnit(m.getCurrencyUnit());
                money.setAmount(m.getAmount());
            } else {
                money.setAmount(money.getAmount().add(m.getAmount()));
            }
        });
        return money;
    }).collect(Collectors.toList());
List List=inputList.stream()
.collect(收集器.groupingBy(Money::getCurrencyUnit))
.values().stream().map(ml->{
钱=新钱;
ml.forEach(m->{
if(money.getCurrencyUnit()==null){
money.setCurrencyUnit(m.getCurrencyUnit());
money.setAmount(m.getAmount());
}否则{
money.setAmount(money.getAmount().add(m.getAmount());
}
});
退钱;
}).collect(Collectors.toList());

您可以使用
groupingBy
收集器按
CurrencyUnit
对对象进行分组。没有第二个参数,
groupingBy
方法将元素收集到一个列表中。但是,如果需要其他内容,也可以指定下游收集器

对于
int
long
可以使用
collector::summingit
collector::summingLong
。对于
BigDecimal
,您可以回到
collector::reduce

import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.reducing;

Map<CurrencyUnit, BigDecimal> result = moneyList.stream()
    .collect(
        groupingBy(
            Money::getCurrencyUnit,
            reducing(BigDecimal.ZERO, Money::getAmount, BigDecimal::add)));
导入静态java.util.stream.Collectors.groupingBy;
导入静态java.util.stream.Collectors.reduction;
映射结果=moneyList.stream()
.收集(
分组依据(
货币:getCurrencyUnit,
减少(BigDecimal.ZERO,Money::getAmount,BigDecimal::add));

编辑:您还可以创建
列表

List result=moneyList.stream()
.收集(
分组依据(
货币:getCurrencyUnit,
减少(BigDecimal.ZERO,Money::getAmount,BigDecimal::add)))
.entrySet().stream()
.map(e->newmoney(e.getKey(),e.getValue())
.collect(toList());

谢谢。这很接近我所需要的,但是你的代码给了我一张
地图
。你不可能拿回
列表
集合
?(不需要手动创建新的
货币
对象等)就在5分钟前,我想到了迭代入口集的想法,但我想:那真的很难看,一定有更性感/优雅的东西。
--
但我认为你给出的答案是唯一的方法。
--
刚才我想:
moneyStream.collector(Collectors.groupingBy(m->m.getCurrencyUnit());
然后使用生成的
Map
Map.values().stream()
生成一个
列表
?!
List<Money> list = inputList.stream()
    .collect(Collectors.groupingBy(Money::getCurrencyUnit))
    .values().stream().map(ml -> {
        Money money = new Money();
        ml.forEach(m -> {
            if(money.getCurrencyUnit() == null) {
                money.setCurrencyUnit(m.getCurrencyUnit());
                money.setAmount(m.getAmount());
            } else {
                money.setAmount(money.getAmount().add(m.getAmount()));
            }
        });
        return money;
    }).collect(Collectors.toList());
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.reducing;

Map<CurrencyUnit, BigDecimal> result = moneyList.stream()
    .collect(
        groupingBy(
            Money::getCurrencyUnit,
            reducing(BigDecimal.ZERO, Money::getAmount, BigDecimal::add)));
List<Money> result = moneyList.stream()
    .collect(
        groupingBy(
            Money::getCurrencyUnit,
            reducing(BigDecimal.ZERO, Money::getAmount, BigDecimal::add)))
    .entrySet().stream()
    .map(e -> new Money(e.getKey(), e.getValue())
    .collect(toList());