我有一份税单:
TaxLine = title:"New York Tax", rate:0.20, price:20.00
TaxLine = title:"New York Tax", rate:0.20, price:20.00
TaxLine = title:"County Tax", rate:0.10, price:10.00
TaxLine类是
public class TaxLine {
private BigDecimal price;
private BigDecimal rate;
private String title;
}
我想根据独特title
和rate
将它们合并,然后添加price
,预期:
TaxLine = title:"New York Tax", rate:0.20, price:40.00
TaxLine = title:"County Tax", rate:0.10, price:10.00
如何在Java 8中执行此操作?
Group by multiple field names in java 8,不是对一个字段进行求和,它只能按两个字段进行分组。
答案 0 :(得分:9)
主体与链接问题中的主体相同,您只需要一个不同的下游收集器来总结:
List<TaxLine> flattened = taxes.stream()
.collect(Collectors.groupingBy(
TaxLine::getTitle,
Collectors.groupingBy(
TaxLine::getRate,
Collectors.reducing(
BigDecimal.ZERO,
TaxLine::getPrice,
BigDecimal::add))))
.entrySet()
.stream()
.flatMap(e1 -> e1.getValue()
.entrySet()
.stream()
.map(e2 -> new TaxLine(e2.getValue(), e2.getKey(), e1.getKey())))
.collect(Collectors.toList());
答案 1 :(得分:1)
一种方法是为您要分组的字段集创建一个对象。可以构建该类以提供好的辅助方法。
所以,你原来的课程就这样完成了:
public final class TaxLine {
private String title;
private BigDecimal rate;
private BigDecimal price;
public TaxLine(String title, BigDecimal rate, BigDecimal price) {
this.title = title;
this.rate = rate;
this.price = price;
}
public String getTitle() {
return this.title;
}
public BigDecimal getRate() {
return this.rate;
}
public BigDecimal getPrice() {
return this.price;
}
@Override
public String toString() {
return "TaxLine = title:\"" + this.title + "\", rate:" + this.rate + ", price:" + this.price;
}
}
分组助手类的定义如下:
public final class TaxGroup {
private String title;
private BigDecimal rate;
public static TaxLine asLine(Entry<TaxGroup, BigDecimal> e) {
return new TaxLine(e.getKey().getTitle(), e.getKey().getRate(), e.getValue());
}
public TaxGroup(TaxLine taxLine) {
this.title = taxLine.getTitle();
this.rate = taxLine.getRate();
}
public String getTitle() {
return this.title;
}
public BigDecimal getRate() {
return this.rate;
}
@Override
public int hashCode() {
return this.title.hashCode() * 31 + this.rate.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj == null || getClass() != obj.getClass())
return false;
TaxGroup that = (TaxGroup) obj;
return (this.title.equals(that.title) && this.rate.equals(that.rate));
}
}
组合订单项的代码是这样的,分成多行以帮助查看其各个部分:
List<TaxLine> lines = Arrays.asList(
new TaxLine("New York Tax", new BigDecimal("0.20"), new BigDecimal("20.00")),
new TaxLine("New York Tax", new BigDecimal("0.20"), new BigDecimal("20.00")),
new TaxLine("County Tax" , new BigDecimal("0.10"), new BigDecimal("10.00"))
);
List<TaxLine> combined =
lines
.stream()
.collect(Collectors.groupingBy(TaxGroup::new,
Collectors.reducing(BigDecimal.ZERO,
TaxLine::getPrice,
BigDecimal::add)))
.entrySet()
.stream()
.map(TaxGroup::asLine)
.collect(Collectors.toList());
然后您可以打印输入/输出:
System.out.println("Input:");
lines.stream().forEach(System.out::println);
System.out.println("Combined:");
combined.stream().forEach(System.out::println);
产生这个:
Input:
TaxLine = title:"New York Tax", rate:0.20, price:20.00
TaxLine = title:"New York Tax", rate:0.20, price:20.00
TaxLine = title:"County Tax", rate:0.10, price:10.00
Combined:
TaxLine = title:"New York Tax", rate:0.20, price:40.00
TaxLine = title:"County Tax", rate:0.10, price:10.00
答案 2 :(得分:0)
无法总结分组字段可以通过在Taxline类中定义一个名为TitleRate的新类来实现,如下所示。
class Taxline{
public static class TitleRate {
public TitleRate(String title, int taxline) {
...
}
}
public TitleRate getTitleRate() {
return new TitleRate(title, taxline);
}
}
要通过对标题和税率进行分组来汇总价格,可以使用以下内容。
Map<TitleRate, List<Taxline>> groupedData = people.collect(Collectors.groupingBy(Taxline::getTitleRate));
List<Taxline> groupedTaxLines = new ArrayList<Taxline>();
BigDecimal groupedRate = BigDecimal.ZERO;
for (Map<TitleRate, List<Taxline>> entry : groupedData.entrySet())
{
for(Taxline taxline : entry.getValue()){
groupedRate = groupedRate.add(taxline.getPrice());
}
groupedTaxLines.add(new Taxline(entry.getKey().getTitle, entry.getKey().getRate(), groupedRate));
groupedRate = BigDecimal.ZERO;
}