首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >java 8群多属性

java 8群多属性
EN

Stack Overflow用户
提问于 2018-06-28 02:18:38
回答 1查看 244关注 0票数 0

我有如下集合元素的列表。我想要groupBy多个字段,比如productCode,然后用于产品购买类型。

代码语言:javascript
运行
复制
class Product{
    private String productCode;
    // this is ENUM with 2 possible values "ONLINE" or "INSTORE"
    private String productPurchaseType; 
    private String productCost;
    ...
}

可能的输出应该类似于

代码语言:javascript
运行
复制
ROW1::ProductCode1, Count of ONLINE,Count of INSTORE,Min, Max
ROW2::ProductCode2, Count of ONLINE,Count of INSTORE, Min, Max

我使用了下面的代码,但是它没有给出在线和安装的计数

代码语言:javascript
运行
复制
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);
}

某个在java8groupby上工作的人能让我知道做这件事的最佳方法吗?

谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-28 03:33:11

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

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

首先,我重新定义了Product,使其具有更好的字段类型:

代码语言:javascript
运行
复制
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;
    }
}

然后,结果收集器类:

代码语言:javascript
运行
复制
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;
    }
}

演示

代码语言:javascript
运行
复制
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);

输出

代码语言:javascript
运行
复制
BREAD=[online: 0, instore: 1, min: 7.48, max: 7.48]
MILK=[online: 2, instore: 1, min: 3.99, max: 4.95]
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51073787

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档