假设我有一个对象列表:
objList
Integer id Double price String userCode
1 10.5 AAA
2 9.5 AAA
3 10.0 AAA
4 10.0 BBB
5 10.0 BBB
我想修改列表,以便我可以按userCode分组并汇总价格,如下所示:
objList
Integer id Double price String userCode
1 30.0 AAA
4 20.0 BBB
我如何在Java 8中使用lambda实现此目的?如果可能的话,我希望在不创建新列表且不丢失其他对象字段(例如本例中的id)的情况下实现这一目标。我已经看到了其他答案,但是所有其他答案都需要创建新列表或集合。
我已经尝试过:
Collection<Obj1> objListSorted = objList.stream().collect(
toMap(
f -> f.getId(),
Function.identity(),
(s, a) -> new Obj1(
(int) s.getId(),
s.getPrice() + a.getPrice(),
s.getUserCode()
))
)
.values();
但是实际上,我正在使用具有80多个字段的模型类,因此我想通过不创建Obj1的新实例来实现这一点。我确实想保留组中的第一个ID,以及保留对象的所有其他字段。另外,如果可能的话,我想将最终输出作为列表而不是集合。
答案 0 :(得分:1)
您可以将modelBuilder.Entity<Tag>().ToTable("Tag");
与下游groupingBy
一起使用。您可以使用Collector
来添加价格,但是会返回您不想要的reducing
,但是可以保证它存在,因此您可以Optional
得出结果。
get()
由于创建的值中没有排序,因此要求将其变为Collection<Obj1> added = objList.stream()
.collect(groupingBy(Obj1::getUserCode),
collectingAndThen(
reducing((o1, o2) -> {
// not creating another instance, but: side effect!
o1.setPrice(o1.getPrice()+o2.getPrice());
return o1;
}),
opt -> opt.get()
))
.values();
几乎没有意义,因此添加的任何内容都是任意的。你当然可以做
List
,然后输入您的List<Obj1> asList = new ArrayList<>(added);
。如果您想对结果进行排序,则可以使用List
和适用的groupingBy
来进行TreeMap
,这样可以保证Comparator
的结果也可以按此排序(不过,您仍然需要将其设置为values()
)。
答案 1 :(得分:1)
尝试一下
一种实现方法是
List<Pricing> allPricings = getAllPricings();
List<Pricing> result = allPricings.stream()
.collect(Collectors.groupingBy(Pricing::getUserCode))
.entrySet().stream()
.map(e -> e.getValue().stream()
.reduce((f1,f2) -> new Pricing(f1.getId(),f1.getPrice() + f2.getPrice(),f1.getUserCode())))
.map(f -> f.get())
.collect(Collectors.toList());
这是一种更紧凑的方式
Collection<Pricing> result2 =
allPricings.stream()
.collect(groupingBy(Pricing::getUserCode,
collectingAndThen(
reducing((p1, p2)-> new Pricing(p1.getId(),p1.getPrice() + p2.getPrice(),p2.getUserCode())), Optional::get)))
.values();
如果您不想创建该对象,请尝试以下对象。但是此实现的副作用是它会更改原始列表的内容,因此最好不要使用原始列表,而要使用克隆的列表。
Collection<Pricing> result3 =
allPricings.stream()
.collect(groupingBy(Pricing::getUserCode,
collectingAndThen(
reducing((p1, p2)-> {
p1.setPrice(p1.getPrice() + p2.getPrice());
return p1;
}), Optional::get)))
.values();
getAllPricings的示例功能
private static List<Pricing> getAllPricings() {
List<Pricing> pricings = new ArrayList<>();
pricings.add(new Pricing(1, 10.5, "AAA"));
pricings.add(new Pricing(2, 9.5, "AAA"));
pricings.add(new Pricing(3, 10.0, "AAA"));
pricings.add(new Pricing(4, 10.0, "BBB"));
pricings.add(new Pricing(5, 10.0, "BBB"));
return pricings;
}
结果
[
{
"id": 1,
"price": 30,
"userCode": "AAA"
},
{
"id": 4,
"price": 20,
"userCode": "BBB"
}
]