流分组由一个字段然后合并所有其他
我有流分组的问题。流分组由一个字段然后合并所有其他
List<FAR> listFar = farList.stream().filter(f -> !f.getStatus().equals(ENUM.STATUS.DELETED))
.collect(Collectors.toList());
List<HAUL> haulList = listFar.stream().map(f -> f.getHaul()).flatMap(f -> f.stream())
.collect(Collectors.toList());
它按物种分组,但一切都很好,但HAUL还有其他属性。
Map<Specie, List<HAUL>> collect = haulList.stream().collect(Collectors.groupingBy(HAUL::getSpecie));
属性:
-
haul.getFishCount();
(整数) -
haul.getFishWeight();
(BigDecimal)的
是否有可能组由HAUL::getSpecie
(由种),而且 “合并” 在一起那两个额外的领域,所以我有总计?
例如:我有3个HAUL元素,其中鱼类物种A的重量为50/30/10千克。
我可以按品种分组并且总重量是多少?
如果我理解正确的:
haulsList
.stream()
.collect(Collectors.groupingBy(HAUL::getSpecie,
Collectors.collectingAndThen(Collectors.toList(),
list -> {
int left = list.stream().mapToInt(HAUL::getFishCount).sum();
BigDecimal right = list.stream().map(HAUL::getFishWeight).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
return new AbstractMap.SimpleEntry<>(left, right);
})));
有做一个表格:
.stream()
.collect(Collectors.groupingBy(HAUL::getSpecie,
Collectors.summingInt(HAUL::getFishCount)));
或
.stream()
.collect(Collectors.groupingBy(HAUL::getSpecie,
Collectors.mapping(HAUL::getFishWeight, Collectors.reducing((x, y) -> x.add(y)))));
但你不能真正使这些在该法同时。
谢谢您的解决方案! – Kefirchiks
您可以使用mapping
和reduce
例如:
class Foo { int count; double weight; String spice; }
List<Foo> fooList = Arrays.asList(
new Foo(1,new BigDecimal(10), "a"),
new Foo(2,new BigDecimal(38), "a"),
new Foo(5,new BigDecimal(2), "b"),
new Foo(4,new BigDecimal(8), "b"));
Map<String,Optional<BigDecimal>> spieceWithTotalWeight = fooList.stream().
collect(
groupingBy(
Foo::getSpice,
mapping(
Foo::getWeight,
Collectors.reducing(BigDecimal::add)
)
)
);
System.out.println(spieceWithTotalWeight); // {a=Optional[48], b=Optional[10]}
我希望这有助于。
我有Integer(count)和BigDecimal作为权重。 你总结的是什么意思? – Kefirchiks
@Kefirchiks,我已经更新了我的答案。我认为体重有双重类型。我很抱歉的混淆。 –
如果我正确地得到你的问题,你想每个物种的总数count * weight
。
您可以通过使用Collectors.groupingBy
与下游收集器减少了在每个物种的HAUL
列表中的haul.getFishCount() * haul.getFishWeight()
总和做到这一点:
Map<Specie, BigDecimal> result = haulList.stream()
.collect(Collectors.groupingBy(haul -> haul.getSpecie(),
Collectors.mapping(haul ->
new BigDecimal(haul.getFishCount()).multiply(haul.getFishWeight()),
Collectors.reducing(BigDecimal::plus))));
这将得到count * weight
每个物种的总和。如果你可以将以下方法添加到您的Haul
类:
public BigDecimal getTotalWeight() {
return new BigDecimal(getFishCount()).multiply(getFishWeight());
}
然后,收集流会更容易和更具可读性:
Map<Specie, BigDecimal> result = haulList.stream()
.collect(Collectors.groupingBy(haul -> haul.getSpecie(),
Collectors.mapping(haul -> haul.getTotalWeight(),
Collectors.reducing(BigDecimal::plus))));
编辑:毕竟,似乎你想为每个领域单独的总和...
我会使用Collectors.toMap
与此合并功能。下面的代码:
Map<Specie, List<BigDecimal>> result = haulList.stream()
.collect(Collectors.toMap(
haul -> haul.getSpecie(),
haul -> Arrays.asList(
new BigDecimal(haul.getFishCount()),
haul.getFishWeight()),
(list1, list2) -> {
list1.set(0, list1.get(0).plus(list2.get(0)));
list1.set(1, list1.get(1).plus(list2.get(1)));
return list1;
}));
它使用2个元素的列表,以存储在索引0
鱼计数和鱼体重索引1
每一个硬币。
适用于繁殖目的。但我只是想分组,然后获得单独元素的总和。 – Kefirchiks
@Kefirchiks我已经更新了答案,以显示总结两个单独的字段。 –
你的意思是把这些加在一起? 'getFishWeight'和'getFishCount'?或每个单独的总和? – Eugene
按物种分组,然后通过getFishCount()和getFishWeight()获得HAUL对象 - 所以这两个字段具有每个物种的总和(因为它们被分组)。 – Kefirchiks
一般而言 - 每个分组物种的独立字段。 – Kefirchiks