java 8具有公共多个字段的对象列表中的总和字段

java 8具有公共多个字段的对象列表中的总和字段,java,java-8,lombok,Java,Java 8,Lombok,我有这个物品清单 List<DetailDto> details; 使用此列表 [ { "category1": "ABC", "category2": 30, "price": 195, "totalPrice": null }, { "category1": "ABC", "category2": 30, "price": 195, "totalPrice": null }, { "ca

我有这个物品清单

List<DetailDto> details;
使用此列表

[
  {
    "category1": "ABC",
    "category2": 30,
    "price": 195,
    "totalPrice": null
  },
  {
    "category1": "ABC",
    "category2": 30,
    "price": 195,
    "totalPrice": null
  },
  {
    "category1": "ABC",
    "category2": 30,
    "price": 195,
    "totalPrice": null
  },
  {
    "category1": "ABC",
    "category2": 30,
    "price": 390,
    "totalPrice": null
  },
  {
    "category1": "ABC",
    "category2": 30,
    "price": 390,
    "totalPrice": null
  },
  {
    "category1": "DEF",
    "category2": 30,
    "price": 455,
    "totalPrice": null
  },
  {
    "category1": "DEF",
    "category2": 30,
    "price": 455,
    "totalPrice": null
  },
  {
    "category1": "DEF",
    "category2": 30,
    "price": 455,
    "totalPrice": null
  },
  {
    "category1": "DEF",
    "category2": 30,
    "price": 455,
    "totalPrice": null
  },
  {
    "category1": "GHI",
    "category2": 1,
    "price": 18000,
    "totalPrice": null
  }
]
我想通过将
price
字段汇总到
totalPrice
字段中来创建另一个
List
对象,其中条件为:

  • 字符串
    类别1
    是常见的
  • 整数
    类别2
    是常见的
  • 整数
    price
    是常见的
在这一点上,我有这个

List summaredlist=detail().stream()
.collect(收集器.groupingBy(DetailDto::category1,
Collector.groupingBy(DetailDto::category2,
Collectors.groupby(DetailDto::price)))
.values()
.stream()
.flatMap(c1->c1.values().stream())
.flatMap(c2->c2.values().stream())
.collect(Collectors.toList());
返回我的
列表

我不知道怎么做才对,在我试过这个之后

summaredList.stream().map(dto->dto.stream().reduce((x,y)->newdetaildto(x.productCode(),x.productQt(),x.orderPrice(),Integer.sum(x.orderPrice(),y.orderPrice()).orElse(null.collect(collector.toList());
它会回来的

[
  {
    "category1": "ABC",
    "category2": 30,
    "price": 195,
    "totalPrice": 390
  },
  {
    "category1": "ABC",
    "category2": 30,
    "price": 390,
    "totalPrice": 780
  },
  {
    "category1": "DEF",
    "category2": 30,
    "price": 455,
    "totalPrice": 910
  },
  {
    "category1": "GHI",
    "category2": 1,
    "price": 18000,
    "totalPrice": null
  }
]
我真正需要的是

[
  {
    "category1": "ABC",
    "category2": 30,
    "price": 195,
    "totalPrice": 585
  },
  {
    "category1": "ABC",
    "category2": 30,
    "price": 390,
    "totalPrice": 780
  },
  {
    "category1": "DEF",
    "category2": 30,
    "price": 455,
    "totalPrice": 1820
  },
  {
    "category1": "GHI",
    "category2": 1,
    "price": 18000,
    "totalPrice": 18000
  }
]

你们能帮我吗?

这里有一种可能性:使用组合键立即分组:

.collect(Collectors.groupingBy(DetailDto::key, Collectors.summarizingInt(DetailDto::getPrice)))
请参阅DetailDto.java中的
Key
的定义(注意eclipse生成的
hashCode
equals
方法):

Main.java

import java.io.IOException;
import java.util.IntSummaryStatistics;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;

public class Main {

    public static void main(String[] args) throws IOException {
        DetailDto[] values = new ObjectMapper().readerFor(DetailDto[].class)
                .readValue(Main.class.getResourceAsStream("data.json"));
//      for (DetailDto dto : values) {
//          display(dto);
//      }

        Map<Key, IntSummaryStatistics> res = Stream.of(values)
                .collect(Collectors.groupingBy(DetailDto::key, Collectors.summarizingInt(DetailDto::getPrice)));

        Stream<DetailDto> agg = res.entrySet().stream().map(e -> new DetailDto(e.getKey().category1,
                e.getKey().category2, e.getKey().price, (int) e.getValue().getSum()));

        agg.forEach(Main::display);

    }

    protected static void display(DetailDto dto) {
        final ObjectWriter json = new ObjectMapper().writerFor(DetailDto.class).withDefaultPrettyPrinter();
        try {
            System.out.println(json.writeValueAsString(dto));
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }
}
import java.io.IOException;
导入java.util.IntSummaryStatistics;
导入java.util.Map;
导入java.util.stream.collector;
导入java.util.stream.stream;
导入com.fasterxml.jackson.core.JsonProcessingException;
导入com.fasterxml.jackson.databind.ObjectMapper;
导入com.fasterxml.jackson.databind.ObjectWriter;
公共班机{
公共静态void main(字符串[]args)引发IOException{
DetailDto[]值=新的ObjectMapper().Reader(DetailDto[]类)
.readValue(Main.class.getResourceAsStream(“data.json”);
//对于(详细数据到dto:值){
//显示器(dto);
//      }
Map res=流(值)
.collect(Collectors.groupingBy(DetailDto::key,Collectors.summaringit(DetailDto::getPrice));
Stream agg=res.entrySet().Stream().map(e->new DetailDto(e.getKey().category1,
e、 getKey().category2,e.getKey().price,(int)e.getValue().getSum());
agg.forEach(主::显示);
}
受保护的静态无效显示(DetailDto到dto){
final ObjectWriter json=new ObjectMapper().writerFor(DetailDto.class).withDefaultPrettyPrinter();
试一试{
System.out.println(json.writeValueAsString(dto));
}捕获(JsonProcessingException e){
抛出新的运行时异常(e);
}
}
}

HTH!

根据
类别1
类别2
价格
为POJO实现相等,并使用合并功能收集toMap,更新
总价
import java.io.IOException;
import java.util.IntSummaryStatistics;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;

public class Main {

    public static void main(String[] args) throws IOException {
        DetailDto[] values = new ObjectMapper().readerFor(DetailDto[].class)
                .readValue(Main.class.getResourceAsStream("data.json"));
//      for (DetailDto dto : values) {
//          display(dto);
//      }

        Map<Key, IntSummaryStatistics> res = Stream.of(values)
                .collect(Collectors.groupingBy(DetailDto::key, Collectors.summarizingInt(DetailDto::getPrice)));

        Stream<DetailDto> agg = res.entrySet().stream().map(e -> new DetailDto(e.getKey().category1,
                e.getKey().category2, e.getKey().price, (int) e.getValue().getSum()));

        agg.forEach(Main::display);

    }

    protected static void display(DetailDto dto) {
        final ObjectWriter json = new ObjectMapper().writerFor(DetailDto.class).withDefaultPrettyPrinter();
        try {
            System.out.println(json.writeValueAsString(dto));
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }
}