具有公共多个字段的对象列表中的java 8 sum字段
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了具有公共多个字段的对象列表中的java 8 sum字段相关的知识,希望对你有一定的参考价值。
我有这个对象列表
List<DetailDto> details;
@Value
public class DetailDto implements Serializable {
String category1;
Integer category2;
Integer price;
transient Integer totalPrice;
}
有这个清单
[
{
"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
}
]
我想通过将List<DetailDto>
字段汇总到price
字段来制作另一个totalPrice
对象,其中条件是:
- 字符串
category1
很常见 - 整数
category2
很常见 - 整数
price
很常见
在这一点上,我有这个
List<List<DetailDto>> summarizedList = detail().stream()
.collect(Collectors.groupingBy(DetailDto::category1,
Collectors.groupingBy(DetailDto::category2,
Collectors.groupingBy(DetailDto::price))))
.values()
.stream()
.flatMap(c1 -> c1.values().stream())
.flatMap(c2 -> c2.values().stream())
.collect(Collectors.toList());
这让我回来List<List<DetailDto>>
在我尝试之后,我不知道该怎么做
summarizedList.stream().map(dto -> dto.stream().reduce((x,y) -> new DetailDto(x.productCode(), x.productQt(), x.orderPrice(), Integer.sum(x.orderPrice(), y.orderPrice()).orElse(null).collect(Collectors.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
方法):
import java.io.Serializable;
@SuppressWarnings("serial")
public class DetailDto implements Serializable {
String category1;
Integer category2;
Integer price;
transient Integer totalPrice;
public DetailDto() {
}
public DetailDto(String category1, Integer category2, Integer price, Integer totalPrice) {
super();
this.category1 = category1;
this.category2 = category2;
this.price = price;
this.totalPrice = totalPrice;
}
public String getCategory1() {
return category1;
}
public void setCategory1(String category1) {
this.category1 = category1;
}
public Integer getCategory2() {
return category2;
}
public void setCategory2(Integer category2) {
this.category2 = category2;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
public Integer getTotalPrice() {
return totalPrice;
}
public void setTotalPrice(Integer totalPrice) {
this.totalPrice = totalPrice;
}
Key key() {
return new Key(category1, category2, price);
}
}
class Key {
String category1;
Integer category2;
Integer price;
public Key(String category1, Integer category2, Integer price) {
super();
this.category1 = category1;
this.category2 = category2;
this.price = price;
}
public String getCategory1() {
return category1;
}
public Integer getCategory2() {
return category2;
}
public Integer getPrice() {
return price;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((category1 == null) ? 0 : category1.hashCode());
result = prime * result + ((category2 == null) ? 0 : category2.hashCode());
result = prime * result + ((price == null) ? 0 : price.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Key other = (Key) obj;
if (category1 == null) {
if (other.category1 != null)
return false;
} else if (!category1.equals(other.category1))
return false;
if (category2 == null) {
if (other.category2 != null)
return false;
} else if (!category2.equals(other.category2))
return false;
if (price == null) {
if (other.price != null)
return false;
} else if (!price.equals(other.price))
return false;
return true;
}
}
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);
}
}
}
HTH!
以上是关于具有公共多个字段的对象列表中的java 8 sum字段的主要内容,如果未能解决你的问题,请参考以下文章
检查自定义对象列表是不是与 Java 8 中的属性具有相同的值