Java8-一个dto中有多少个字段?

Java8-一个dto中有多少个字段?,java,java-8,java-stream,Java,Java 8,Java Stream,假设我有这样一个类项目: class Item { private long id; private BigDecimal value1; private BigDecimal value2; private BigDecimal value3; } TotalItem totals = list.stream().collect( Collector.of(() -> new ItemStatsSummary(Math

假设我有这样一个类项目:

class Item {  
    private long id;  
    private BigDecimal value1;  
    private BigDecimal value2;  
    private BigDecimal value3;  
}  
TotalItem totals = list.stream().collect(
      Collector.of(() -> new ItemStatsSummary(MathContext.DECIMAL64),
                   ItemStatsSummary::accept,
                   ItemStatsSummary::combine,
                   ItemStatsSummary::getSum)
    )
然后我有一个包含许多iten的列表,我想知道每个值的总和:

所以,我知道我可以做一些像

BigDecimal v1 = list.stream().map(Item::value1).reduce(BigDecimal.ZERO, BigDecimal::add);
但是,通过这种方式,我需要对每个值执行相同的操作,我想知道是否有某种方法可以将每个属性相加为一个数据,如:

class TotalItem {  
    private BigDecimal value1;  
    private BigDecimal value2;  
    private BigDecimal value3;  
}  

TotalItem t = list.stream().map(???).reduce(BigDecimal.ZERO, BigDecimal::add);
这可能吗


提前感谢。

我没有测试它,但我认为您可以在项目上实现添加功能,如:

然后做:

Item t = list.stream().reduce(BigDecimal.ZERO, Item::add);

我没有测试它,但我认为您可以在项目上实现添加功能,如:

然后做:

Item t = list.stream().reduce(BigDecimal.ZERO, Item::add);

我假设Item/TotalItem是非常大的对象,这将使手工编写toTotalItem和SummarSetTotalItem成为一项艰巨的工作。一个完全是陈词滥调,容易出错的人

将数据结构更改为列表或地图-这使得摘要更简单,但以代码可读性和类型安全性为代价

使用反射来迭代

上面的代码并不整洁,但应该显示概念。同样的概念可用于总结

这减少了需要编写的代码量,但以运行时速度为代价。反射也很难做到正确和神奇,这是一些开发人员不喜欢的


更快的选择是添加摘要的自定义注释。然而,这将是一项巨大的工作。如果有大量的对象需要这样做,那么它可能是有意义的。像反射一样,它很难获得一些开发人员不喜欢的正确和神奇。幸运的是,您不需要构建步骤,因为Javac本机支持注释处理

我假设Item/TotalItem是非常大的对象,这将使手工编写toTotalItem和SummaresetTotalItem成为一项艰巨的工作。一个完全是陈词滥调,容易出错的人

将数据结构更改为列表或地图-这使得摘要更简单,但以代码可读性和类型安全性为代价

使用反射来迭代

上面的代码并不整洁,但应该显示概念。同样的概念可用于总结

这减少了需要编写的代码量,但以运行时速度为代价。反射也很难做到正确和神奇,这是一些开发人员不喜欢的


更快的选择是添加摘要的自定义注释。然而,这将是一项巨大的工作。如果有大量的对象需要这样做,那么它可能是有意义的。像反射一样,它很难获得一些开发人员不喜欢的正确和神奇。幸运的是,您不需要构建步骤,因为Javac本机支持注释处理

下面的方法怎么样

TotalItem t = new TotalItem();

list.stream().forEach(item -> {
   t.value1+ = item.value1;
   t.value2+ = item.value2;
   t.value3+ = item.value3;
});

下面的方法怎么样

TotalItem t = new TotalItem();

list.stream().forEach(item -> {
   t.value1+ = item.value1;
   t.value2+ = item.value2;
   t.value3+ = item.value3;
});

这个答案的灵感来自JDK做类似操作的方式。也就是说,我将引用类

首先,我们为收集的大小数信息定义一个持有者:

public class BigDecimalSummaryStats {
  private long count;
  private MathContext mc;
  private BigDecimal sum = BigDecimal.ZERO;
  private BigDecimal max;
  private BigDecimal min;

  public BigDecimalSummaryStats(MathContext mathCtx) {
    mc = requireNonNull(mathCtx);
  }

  public Supplier<BigDecimalSummaryStats> supplier(MathContext ctx) {
    return () -> new BigDecimalSummaryStats(ctx);
  }

  public void accept(BigDecimal value) {
    requireNonNull(value);
    count++;
    sum = sum.add(value, mc);
    min = min.min(value);
    max = max.max(value);
  }

  public void combine(BigDecimalSummaryStats other) {
    requireNonNull(other);
    count += other.count;
    sum = sum.add(other.sum, mc);
    min = min.min(other.min);
    max = max.max(other.max);
  }

  public long getCount() {
    return count;
  }

  public BigDecimal getSum() {
    return sum;
  }
  public BigDecimal getMax() {
    return max;
  }
  public BigDecimal getMin() {
    return min;
  }
  public BigDecimal getAverage() {
    long c = getCount();
    return c == 0 ? BigDecimal.ZERO : getSum().divide(BigDecimal.valueOf(c), mc);
  }
}
这种方法的缺点:

与临时解决方案相比,开发时间稍长。 被专业人士远远压倒,或者至少我确信:

遵循关注点分离原则:条目统计实际上并不关心如何收集特定字段的摘要:它们可以相信BigDecimalSummary是有效的 可测试:每个部件都可以在自己的套件中进行测试。您可以相信,由于每个字段使用相同的API,因此它们的工作方式是相同的。 灵活:getFunction。。。方法公开了大量的可能性:您可以收集第一个字段的总和、第二个字段的平均值和第三个字段的最小值(如果需要)。
这个答案的灵感来自JDK做类似操作的方式。也就是说,我将引用类

首先,我们为收集的大小数信息定义一个持有者:

public class BigDecimalSummaryStats {
  private long count;
  private MathContext mc;
  private BigDecimal sum = BigDecimal.ZERO;
  private BigDecimal max;
  private BigDecimal min;

  public BigDecimalSummaryStats(MathContext mathCtx) {
    mc = requireNonNull(mathCtx);
  }

  public Supplier<BigDecimalSummaryStats> supplier(MathContext ctx) {
    return () -> new BigDecimalSummaryStats(ctx);
  }

  public void accept(BigDecimal value) {
    requireNonNull(value);
    count++;
    sum = sum.add(value, mc);
    min = min.min(value);
    max = max.max(value);
  }

  public void combine(BigDecimalSummaryStats other) {
    requireNonNull(other);
    count += other.count;
    sum = sum.add(other.sum, mc);
    min = min.min(other.min);
    max = max.max(other.max);
  }

  public long getCount() {
    return count;
  }

  public BigDecimal getSum() {
    return sum;
  }
  public BigDecimal getMax() {
    return max;
  }
  public BigDecimal getMin() {
    return min;
  }
  public BigDecimal getAverage() {
    long c = getCount();
    return c == 0 ? BigDecimal.ZERO : getSum().divide(BigDecimal.valueOf(c), mc);
  }
}
这种方法的缺点:

与临时解决方案相比,开发时间稍长。 被专业人士远远压倒,或者至少我确信:

遵循关注点分离原则:条目统计实际上并不关心如何收集特定字段的摘要:它们可以相信BigDecimalSummary是有效的 可测试:每个部件都可以在自己的套件中进行测试。您可以相信,由于每个字段使用相同的API,因此它们的工作方式是相同的。 灵活:getFunction。。。方法公开了大量的可能性:您可以收集第一个字段的总和、第二个字段的平均值和第三个字段的最小值(如果需要)。
您需要为统计数据创建新类。每个值都是单独的,这意味着结果有3个和值,或者同一个和中有三个不同的值?您需要为统计数据创建新类。每个值都是单独的,这意味着结果有三个和值,或者三个不同的值组成同一个和?这不会编译:Item不能分配给TotalItem。这很容易解决。或者不使用TotalItem,因为它完全相同,或者实现ToTotalItem为什么一个项目关心可能性

将其转换为TotalItem的难度?这违反了SRP。是否有必要使用TotalItem来表示聚合?如果要使用reduce,必须先将列表映射到列表,这不太好。没有解决方法。这不会编译:Item不可分配给TotalItem。这很容易解决。或者不使用TotalItem,因为它完全相同,或者实现ToTotalItem为什么项目会关心将其转换为TotalItem的可能性?这违反了SRP。是否有必要使用TotalItem来表示聚合?如果要使用reduce,必须先将列表映射到列表,这不太好。不要在它周围工作。这个不好,因为它有一面effects@maxpovver什么副作用?在foreach中,它会改变foreach之外的变量。若在TotalItem Creation中添加一些新代码,它可能会被破坏。为什么要添加会更改TotalItem并破坏它的代码?你显然不想那样做。如果解决方案很简单,就使用它。不要试图解释不可能出现的异常,这只是执行常规增强for循环的一个捷径。我可以理解map或reduce方法中对副作用的关注,但forEach似乎自然是为了这样的目的而设计的。这个方法很糟糕,因为它有副作用effects@maxpovver什么副作用?在foreach中,它会改变foreach之外的变量。若在TotalItem Creation中添加一些新代码,它可能会被破坏。为什么要添加会更改TotalItem并破坏它的代码?你显然不想那样做。如果解决方案很简单,就使用它。不要试图解释不可能出现的异常,这只是执行常规增强for循环的一个捷径。我可以理解map或reduce方法中对副作用的关注,但forEach似乎自然是为了达到这样的目的。这是对一条删除的评论的回复,该评论抱怨我见过的解决方案,当项目和TotalItem非常大时。因此,其中两个的求和是一个大的、完全枯燥的、容易出错的样板代码。像ApacheCommons使用toString/equals那样实现自动化是有意义的。不过,它需要比上面编写的代码好得多。这是显示该概念的示例代码。当时我玩过注释解决方案,但从未完成原型。我的意思是反射有时是巫毒,我更喜欢更明确。我并不是说这个解决方案不起作用,它是。肯定但是它被封装在一个经过良好测试的库中,比如ApacheCommonsToString/Equals,它工作得非常好。我个人讨厌锅炉板代码。我们有电脑为我们制作锅炉板。那么为什么不使用它们呢。我个人认为像ProjectLombok这样的定制注释方法是解决这个问题的正确方法。一个@summatable注释和一些关于如何总结字段的注释。这是对一条删除的注释的回复,该注释抱怨我见过的解决方案,当Item和TotalItem非常大时。因此,其中两个的求和是一个大的、完全枯燥的、容易出错的样板代码。像ApacheCommons使用toString/equals那样实现自动化是有意义的。不过,它需要比上面编写的代码好得多。这是显示该概念的示例代码。当时我玩过注释解决方案,但从未完成原型。我的意思是反射有时是巫毒,我更喜欢更明确。我并不是说这个解决方案不起作用,它是。肯定但是它被封装在一个经过良好测试的库中,比如ApacheCommonsToString/Equals,它工作得非常好。我个人讨厌锅炉板代码。我们有电脑为我们制作锅炉板。那么为什么不使用它们呢。我个人认为像ProjectLombok这样的定制注释方法是解决这个问题的正确方法。一个@summatable注释和一些关于如何汇总字段的注释。