【问题标题】:Group items in a list in JavaJava中列表中的项目分组
【发布时间】:2020-07-15 08:14:11
【问题描述】:

我有一个对象列表List<WorkingActivityModel> mList = new ArrayList<>();

public class WorkingActivityModel {
   private String name;
   private Sales sales;
   private Shifts shifts;
}

销售模式是:

public class Sales {
    private int product1;
    private int product2;
}

班次模型是:

public class Shifts {
    private int shift1;
    private int shift2;
}

如何按名称对List<WorkingActivity> mList 中的商品进行分组,然后汇总相应的销售额和班次?因此,如果我在列表中有 2 个具有相同名称的项目,那么将它们分组并汇总其销售额和班次?

我尝试过直播但没有成功:

List<WorkingActivityModel> result = mList.stream()
                        .collect(groupingBy(WorkingActivityModel::getName, LinkedHashMap::new, toList()))
                        .values().stream()
                        .flatMap(Collection::stream)
                        .collect(toList());

另一种选择是:

List<WorkingActivity> mList = new ArrayList<>();

HashMap<String, List<WorkingActivityModel>> map = new HashMap<>();

for(WorkingActivityModel o : mList){
    if (!map.containsKey(o.getKey())) {
        List<WorkingActivityModel> list = new ArrayList<>();
        list.add(o);

        map.put(o.getKey(), list);
    } else {
        map.get(o.getKey()).add(o);
    }
}

在这种情况下,我不知道如何将相应的销售额和班次相加

编辑

下面是预期结果的示例:

【问题讨论】:

  • 我有两个问题:1:List&lt;WorkingActivity&gt; 应该是List&lt;WorkingActivityModel&gt;,对吗? 2:你能举个例子吗?
  • 您的最终名单将是什么样子。可以发帖吗?
  • @Ema.jar,我编辑了我的问题,List 它是一个 ArrayList。

标签: java list java-8 grouping


【解决方案1】:

你可以这样做:

 mList.stream()
            .collect(Collectors.toMap(WorkingActivityModel::getName,Function.identity(),
                  (o, o2) -> {
                       o.getSales().sum(o2.getSales());
                       o.getShifts().sum(o2.getShifts());
                       return o;
                   })
           )
           .values()

和:

public Sales sum(Sales s) {
    this.product1 += s.product1;
    this.product2 += s.product2;
    return this;
}

public Shifts sum(Shifts s) {
    this.shift1 += s.shift1;
    this.shift2 += s.shift2;
    return this;
}

【讨论】:

  • 这个解决方案可以解决问题。除了列表没有分组,而是将模型的总和添加到列表中,所以列表有两个项目,这个解决方案添加了另一个具有所需结果的项目。但问题是我只需要有总和的项目。我不知道我是否清楚
【解决方案2】:

您可以使用定义的自定义合并操作来做到这一点,这样执行toMap 会变得稍微容易一些。

Collection<WorkingActivityModel> result = mList.stream()
        .collect(Collectors.toMap(WorkingActivityModel::getName, Function.identity(),
                (a, b) -> WorkingActivityModel.mergeModels(a, b))) // WorkingActivityModel::mergeModels
        .values();

mergeModels 是我在WorkingActivityModel 类中定义的静态方法,例如它处理合并两个相似命名模型的逻辑。

static WorkingActivityModel mergeModels(WorkingActivityModel model1, WorkingActivityModel model2) {
    return new WorkingActivityModel(model1.name,
            Sales.mergeSales(model1.sales, model2.sales),
            Shifts.mergeShifts(model1.shifts, model2.shifts));
}

当然,mergeSalesmergeShifts 遵循相同的模式并且实现起来很简单。

【讨论】:

  • 您好,非常好,按照您的指示,我设法解决了。我像这样mList.stream().collect(Collectors.groupingBy(WorkingActivityModel::getKey, Collectors.reducing(WorkingActivityModel::mergeModels))).values().stream().filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList());流式传输列表@非常感谢。
  • @Erjon 太好了。然后你可能想进一步了解Java Streams: Replacing groupingBy and reducing by toMap
【解决方案3】:

您也可以在自定义数据结构中直接作为 item_add 求和。

import java.util.HashMap;

public class MyHash extends HashMap<String, WorkingActivityModel>
{

    @Override
    public WorkingActivityModel put(String key, WorkingActivityModel value)
    {
        if(this.containsKey(key))
        {
            WorkingActivityModel w = this.get(key);
            value.getSales().setProduct1(w.getSales().getProduct1() + value.getSales().getProduct1());
            value.getSales().setProduct2(w.getSales().getProduct2() + value.getSales().getProduct2());
        //  ... same 
        //  value.getShifts().setShift1(w.getShifts().getShift1() + value.getShifts().getShift1());
        //  value.getShifts().setShift1(w.getShifts().getShift2() + value.getShifts().getShift2());
            super.put(key, value);
        }
        else
        {
            super.put(key, value);
        }
        return value;
    }
    
    public String toString()
    {
        StringBuffer sb = new StringBuffer();
        this.forEach((k,v) -> sb.append(k+",sale_p1="+v.getSales().getProduct1()+",sale_p2="+v.getSales().getProduct2()+"\n"));
        return sb.toString();
    }
    
    public static void main(String args[])
    {
        Sales s1 = new Sales();
        s1.setProduct1(1);
        Sales s2 = new Sales();
        s2.setProduct1(2);
        s2.setProduct2(3);
        MyHash mh = new MyHash();
        
        WorkingActivityModel wam = new WorkingActivityModel();
        wam.setSales(s1);
        wam.setName("n1");
        mh.put(wam.getName(), wam);
        System.out.println(mh);
        
        WorkingActivityModel wam2 = new WorkingActivityModel();
        wam2.setSales(s2);
        wam2.setName("n1");
        mh.put(wam2.getName(), wam2);
        
        System.out.println(mh);
    }
}

...

//same with other class
public class Sales {
    public Sales()
    {
        this.product1 = 0;
        this.product2 = 0;
    }
    public int getProduct1() {
        return product1;
    }
    public void setProduct1(int product1) {
        this.product1 = product1;
    }
    public int getProduct2() {
        return product2;
    }
    public void setProduct2(int product2) {
        this.product2 = product2;
    }
    private int product1;
    private int product2;
}

输出

n1,sale_p1=1,sale_p2=0
n1,sale_p1=3,sale_p2=3

【讨论】:

    【解决方案4】:

    如果我对您的问题的理解是正确的,这可能会有所帮助 -

    List<WorkingActivityModel> mList = generateList(6);
    
    Map<String, WorkingActivityModel> map = mList.stream()
                .collect(groupingBy(WorkingActivityModel::getName))
                .entrySet().stream()
                .collect(Collectors.toMap(entry ->entry.getKey(),
                        entry -> {
                    WorkingActivityModel wam = new WorkingActivityModel();
                    wam.shifts = new Shifts();
                    wam.shifts.shift1 = entry.getValue()
                            .stream()
                            .map(v -> v.shifts.shift1)
                            .reduce(0, Integer::sum);;
                    wam.shifts.shift2 = entry.getValue()
                            .stream()
                            .map(v -> v.shifts.shift2)
                            .reduce(0, Integer::sum);
                    wam.sales = new Sales();
                    wam.sales.product1 = entry.getValue()
                            .stream()
                            .map(v -> v.sales.product1)
                            .reduce(0, Integer::sum);
                    wam.sales.product2 = entry.getValue()
                            .stream()
                            .map(v -> v.sales.product2)
                            .reduce(0, Integer::sum);
                    return wam;
                }));
    

    地图将按名称对工作活动进行分组。 Key 是名称,value 是 WorkingActiviyModel 对象,其中包含班次和产品的总和。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-18
      • 2012-04-25
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      • 2015-02-18
      • 2012-09-30
      • 2019-08-03
      相关资源
      最近更新 更多