gpt4 book ai didi

java 8 groupby多个属性

转载 作者:行者123 更新时间:2023-12-02 11:04:36 25 4
gpt4 key购买 nike

我有如下集合元素列表。我想按产品代码等多个字段进行分组,然后按产品购买类型进行分组。

class Product{
private String productCode;
// this is ENUM with 2 possible values "ONLINE" or "INSTORE"
private String productPurchaseType;
private String productCost;
...
}

可能的输出应该是这样的

ROW1::ProductCode1, Count of ONLINE,Count of INSTORE,Min, Max
ROW2::ProductCode2, Count of ONLINE,Count of INSTORE, Min, Max

我使用了下面的代码,但它没有给出 ONLINE 和 INSTORE 的计数

void groupByMerchantMCCCodeZIP(List<Product> productList) {
Map<String, Map<String, List<Product>>> output = transactionDataList.stream()
.collect(Collectors.groupingBy(Product::getProductCode,
Collectors.groupingBy(Product::productPurchaseType)));
System.out.println(output);
}

从事 java 8 groupby 工作的人可以让我知道执行此操作的最佳方法吗?

谢谢!

最佳答案

要聚合多个值,您应该编写自己的收集器,以获得最佳性能。

编写 Collector 的最简单方法就是调用Collector.of()方法,与结果收集器类结合。下面是一个例子。

首先,我重新定义了 Product 以获得更好的字段类型:

class Product {
public enum PurchaseType { ONLINE, INSTORE }

private final String code;
private final PurchaseType purchaseType;
private final BigDecimal cost;

public Product(String code, PurchaseType purchaseType, String cost) {
this.code = code;
this.purchaseType = purchaseType;
this.cost = new BigDecimal(cost);
}
public String getCode() {
return this.code;
}
public PurchaseType getPurchaseType() {
return this.purchaseType;
}
public BigDecimal getCost() {
return this.cost;
}
}

然后是结果收集器类:

class ProductResult {
private int onlineCount;
private int instoreCount;
private BigDecimal minCost;
private BigDecimal maxCost;

public void add(Product product) {
if (product.getPurchaseType() == Product.PurchaseType.ONLINE)
this.onlineCount++;
else if (product.getPurchaseType() == Product.PurchaseType.INSTORE)
this.instoreCount++;
if (this.minCost == null || product.getCost().compareTo(this.minCost) < 0)
this.minCost = product.getCost();
if (this.maxCost == null || product.getCost().compareTo(this.maxCost) > 0)
this.maxCost = product.getCost();
}
public ProductResult merge(ProductResult that) {
this.onlineCount += that.onlineCount;
this.instoreCount += that.instoreCount;
if (this.minCost == null || that.minCost.compareTo(this.minCost) < 0)
this.minCost = that.minCost;
if (this.maxCost == null || that.maxCost.compareTo(this.maxCost) > 0)
this.maxCost = that.maxCost;
return this;
}
@Override
public String toString() {
return "[online: " + this.onlineCount +
", instore: " + this.instoreCount +
", min: " + this.minCost +
", max: " + this.maxCost + "]";
}
public int getOnlineCount() {
return this.onlineCount;
}
public int getInstoreCount() {
return this.instoreCount;
}
public BigDecimal getMinCost() {
return this.minCost;
}
public BigDecimal getMaxCost() {
return this.maxCost;
}
}

演示

List<Product> productList = Arrays.asList(
new Product("MILK", Product.PurchaseType.ONLINE, "3.99"),
new Product("MILK", Product.PurchaseType.ONLINE, "3.99"),
new Product("MILK", Product.PurchaseType.INSTORE, "4.95"),
new Product("BREAD", Product.PurchaseType.INSTORE, "7.48")
);

Map<String, ProductResult> result = productList.stream()
.collect(Collectors.groupingBy(Product::getCode,
Collector.of(ProductResult::new,
ProductResult::add,
ProductResult::merge,
Characteristics.UNORDERED)));
result.entrySet().forEach(System.out::println);

输出

BREAD=[online: 0, instore: 1, min: 7.48, max: 7.48]
MILK=[online: 2, instore: 1, min: 3.99, max: 4.95]

关于java 8 groupby多个属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51073787/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com