Java 8流按3个字段分组,并按总和和计数进行汇总,以产生单行输出

武子

我知道在论坛中也有类似的问题,但是似乎没有一个问题能够完全解决我的问题。现在我对Java 8还是很陌生,所以请多多包涵。我有一个产品列表,例如:

Input:
name    category    type    cost
prod1       cat2     t1      100.23
prod2       cat1     t2      50.23
prod1       cat1     t3      200.23
prod3       cat2     t1      150.23
prod1       cat2     t1      100.23


Output:
Single line (name, category, type) summing the cost and count of products.




Product {
    public String name;
    public String category;
    public String type;
    public int id;
    public double cost;

}

我需要按名称,类别和类型对其进行分组,并产生一个汇总该数据并得出每个产品的总成本和数量的单个结果。大多数示例显示按两个字段分组并使用单个条件进行汇总。

根据论坛上的建议,我提出了以下分组建议:

    public class ObjectKeys {

    ArrayList<Object> keys;

    public ObjectKeys(Object...searchKeys) {

         keys = new ArrayList<Object>();

            for (int i = 0; i < searchKeys.length; i++) {
                keys.add( searchKeys[i] );
            }
    }

}

然后按如下方式使用它:

Map<String, Map<String, Map<String, List<Product>>>> productsByNameCategoryType =
    products.stream().collect(groupingBy(new ObjectKeys(l.name(), l.category(),l.type())))

但是,如何对上面的代码进行计数和求和?特别适用于具有2个以上字段的分组。有一个更好的方法吗?

就像我提到的Java8那样不好,请帮忙。

holi-java

前提

class Product {
    public String name;
    public String category;
    public String type;
    public int id; 
    //todo:implement equals(), toString() and hashCode()
 }

class Item{
   public Product product;
   public double cost;
}

总结方式

您可以使用Collectors#groupingByCollectors#summarizingDouble汇总按产品分组的项目

List<Item> items = ...; 
Map<Product, DoubleSummaryStatistics> stat = items.stream().collect(groupingBy(
            it -> it.product,
            Collectors.summarizingDouble(it -> it.cost)
));

// get some product summarizing
long count = stat.get(product).getCount();
double sum = stat.get(product).getSum();

//list all product summarizing
stat.entrySet().forEach(it ->
  System.out.println(String.format("%s - count: %d, total cost: %.2f"
        , it.getKey(),it.getValue().getCount(), it.getValue().getSum()));
);

合并具有相同产品的项目

首先,您需要qtyItem课程中添加一个字段

class Item{
   public int qty;
   //other fields will be omitted

   public Item add(Item that) {
        if (!Objects.equals(this.product, that.product)) {
            throw new IllegalArgumentException("Can't be added items"
                     +" with diff products!");
        }
        return from(product, this.cost + that.cost, this.qty + that.qty);
    }

    private static Item from(Product product, double cost, int qty) {
        Item it = new Item();
        it.product = product;
        it.cost = cost;
        it.qty = qty;
        return it;
    }

}

那么您可以使用Collectors#toMap合并具有相同产品的商品:

Collection<Item> summarized = items.stream().collect(Collectors.toMap(
        it -> it.product,
        Function.identity(),
        Item::add
)).values();

最后

您可以看到两种方法都可以做相同的事情,但是第二种方法更容易在流上进行操作。以及我在github中检查过的两种方法的测试,您可以单击并查看更多详细信息:汇总项目合并项目的方法。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Java Stream按02个字段分组,并按2个BigDecimal字段的总和进行聚合

按字段对对象列表进行分组并在其中一个字段中应用二元函数以使用流 java 8 在一行代码中按总和减少它

按多个字段对Java对象列表进行排序,并按特定字段进行分组

Java 8流按多个属性和总和分组

使用流API按Java中的n个字段分组

Java8流分组按枚举和计数

Java 8流库| 对列表中的元素进行分组并计数

Java 8:按值汇总项目列表,并按位置范围重新分组

Java 8 Lambdas按多个字段分组

在多个字段上按对象分组Java 8

Java流按2个字段排序

当计数> 100 Java流时按分组

Java 8:按字段对集合进行分组,然后使用流将集合展平并作为映射值加入集合?

按Java 8流API分组

Java 8流-对元组流进行分组

Java 8流:通过聚合进行分组

Java 8流分组 如果只有一个分组值对象,如何设置字段?

Java Streams:按两个字段对列表进行分组

Java 8:按多个字段分组,然后根据值排序

Java 8:按字段名称对字段值进行分组

java 8流分组通过复合变量的总和

使用Java Stream API按字段分组计算总和

Java 8,整数流,按整数对流的索引进行分组?

Java 8流按包含字符串列表的对象进行分组

使用Java 8流API按多个属性对对象进行分组

Java流分组通过对多个字段求和

在Java 8中通过聚合在多个字段上进行分组

Java流按功能分组

Java流分组按条件