【问题标题】:Java 8 adding values of multiple property of an Object ListJava 8添加对象列表的多个属性的值
【发布时间】:2018-09-23 10:03:34
【问题描述】:

假设我在下面有一个带有 getter 和 setter 的类,但只有默认构造函数。

注意:我不能改变这个类的结构。

class Target {

    private String year;
    private String month;
    private String name;
    private double target;
    private double achieved;


    public String getYear() {
        return year;
    }

    public void setYear(String year) {
        this.year = year;
    }

    public String getMonth() {
        return month;
    }

    public void setMonth(String month) {
        this.month = month;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getTarget() {
        return target;
    }

    public void setTarget(double target) {
        this.target = target;
    }

    public double getAchieved() {
        return achieved;
    }

    public void setAchieved(double achieved) {
        this.achieved = achieved;
    }    
}

我必须根据年份和名称添加目标和实现的列值。

Year Month Name Target Achieved
2018  8    Joey 50.00   10.00
2018  9    Joey 200.00  100.00
2018  9    Fred 200.00  150.00
2018  9    Fred 20.00   50.00

所以输出将是:

Year Month Name Target  Achieved
2018  8    Joey 50.00   10.00
2018  9    Joey 200.00  100.00
2018  9    Fred 220.00  200.00

我看过一个例子,如果我有一个接受参数的构造函数,我如何实现这样的事情,但我对 Group by and sum objects like in SQL with Java lambdas? 的概念不太清楚:

如何仅使用默认构造函数来获得相同类型 List<Target> 但计算多列的值?

【问题讨论】:

  • hm...我已经提供了答案,但现在真正的问题是您想保留哪个个月?遇到顺序的第一个/最后一个?还是最大的?
  • @Eugene 我只想根据月份和名称计算总数。我已经更新了问题。谢谢
  • 因此从您的示例看来,您需要根据此处的 3 件事进行分组:年、月和名称
  • @Eugene 在这个例子中是的。但我正在寻找的是一个灵活的解决方案,我可以根据分组(姓名)、(姓名+年)、(姓名+年+月)获得输出。
  • 所以你想要一个动态分组?您不能简单地创建一个接受您的列表的方法和一个函数,该函数将充当Collectors.toMap 中键的映射函数吗?

标签: java lambda java-8 java-stream


【解决方案1】:

您似乎需要根据三件事进行分组:Year、Month 和 Name,因此可能如下所示:

Collection<Target> merged = yourListOfTargets
            .stream()
            .collect(Collectors.toMap(
                    t -> List.of(t.getYear(), t.getMonth(), t.getName()),
                    Function.identity(),
                    (left, right) -> {
                        left.setTarget(left.getTarget() + right.getTarget());
                        left.setAchieved(left.getAchieved() + right.getAchieved());
                        return left;
                    }))
            .values();

正如 Federico 在 cmets 中提到的,这将改变初始 List 中的元素。你可能会接受它,但如果你不是,你需要用一个复制函数替换Function.identity(),它会从现有的Target 创建一个新的Target。

【讨论】:

  • @FedericoPeraltaSchaffner 我有点迷路了......我在修改什么? :|
  • @FedericoPeraltaSchaffner 对。我会在答案中提到这一点,老实说,我认为这不会对 OP 造成任何问题,但这是一个有效的观点,我承认
【解决方案2】:
public class Test8 {
  static class Target {

    String year;
    int target, achieved;
    String month;
    String name;

    public Target(String string, String string2, String name, int achieved, int target) {

      this.year = string;
      this.month = string2;
      this.target = target;
      this.achieved = achieved;
      this.name = name;
    }

    @Override
    public String toString() {
      return "[year=" + year + 
          ", month=" + month 
          + ", target=" + target 
          + ", achieved=" + achieved
          + ", name="
          + name + "]";
    }

  }// target

  public static void main(String[] args) {

    List<Target> list = Arrays.asList(

        new Target("1993", "9", "Protijayi", 1000, 40), 
        new Target("1993", "9", "Protijayi", 600, 400),
        new Target("1987", "11", "Soudipta", 320, 200),
        new Target("1987", "11", "Soudipta", 500, 900),
        new Target("1985", "9", "Tabu", 300, 200),
        new Target("1986", "9", "Tabu", 700, 200)

    );


        Map<List<String>, Target> map = list
        .stream()
        .collect(
            Collectors.groupingBy(
                ch -> List.of(ch.year, ch.month, ch.name), 
                Collectors.collectingAndThen(

            Collectors.reducing(
    (a, b) -> new Target(a.year, a.month, a.name, a.target + b.target,a.achieved + b.achieved)

            ), Optional::get)

        ));
    System.out.println(" MAP ");
    System.out.println(map);
    System.out.println(".................");
    System.out.println(" MAP.VALUES() ");
    System.out.println(map.values());

  }// main

}

/*
  MAP 
{[1993, 9, Protijayi]=[year=1993, month=9, target=1600, achieved=440, name=Protijayi],
 [1985, 9, Tabu]=[year=1985, month=9, target=200, achieved=300, name=Tabu],
  [1987, 11, Soudipta]=[year=1987, month=11, target=820, achieved=1100, name=Soudipta],
   [1986, 9, Tabu]=[year=1986, month=9, target=200, achieved=700, name=Tabu]}
.................
 MAP.VALUES() 
[[year=1993, month=9, target=1600, achieved=440, name=Protijayi], 
[year=1985, month=9, target=200, achieved=300, name=Tabu],
[year=1987, month=11, target=820, achieved=1100, name=Soudipta],
 [year=1986, month=9, target=200, achieved=700, name=Tabu]]
*/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-24
    • 2019-12-06
    • 2021-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多