use*_*155 6 java java-stream collectors
我想使用Java的流API在对象列表上进行一些计算:
List<Item>.stream()...
本Item类包含许多属性.对于其中一些我需要取集合中所有项目的平均值,对于其他属性我需要做其他形式的计算.我一直在做单独的流/收集器调用来实现这一点,虽然我没有遇到任何性能问题(因为列表大小通常大约为100)我想学习如何更简洁,也就是循环一次.
ItemCalculation itemCalculation = ItemCalculation.builder()
.amountOfItems(itemList.size())
.averagePrice(itemList.stream()
.mapToDouble(item -> item.getPrice())
.average()
.getAsDouble())
.averageInvestmentValue(itemList.stream()
.mapToDouble(item -> getTotalInvestmentValue(item.getInvestmentValue(), item.getInvestmentValuePackaging()))
.average()
.getAsDouble())
.highestWarrantyLimit(itemList.stream()... etc.
Run Code Online (Sandbox Code Playgroud)
我读到了创建一个自定义收集器,但让我的"计算"类只是一行(stream-> customCollector)然后有一个非常臃肿的收集器类来执行实际逻辑似乎有点奇怪.特别是因为以不同的方式收集不同的属性,我需要许多不同的中间计数和其他变量.有什么想法吗?
不幸的是,似乎不可能使用流来合理地改进它,以便它可以在单线程模式下更好地执行。
您在问题中提供的代码很容易理解,并且对于现在的小型集合来说性能足够。
如果您想提高解决方案的性能,您可以以迭代方式对集合进行一次迭代,在单次运行中计算所需的每个输出:
long amountOfItems = 0;
double priseSum = 0;
double highestWarrantyLimit = Double.MIN_VALUE;
for (Item item : itemList) {
amountOfItems++;
priseSum += item.getPrice();
double investmentValue = getTotalInvestmentValue(item.getInvestmentValue(), item.getInvestmentValuePackaging());
if (highestWarrantyLimit < investmentValue) {
highestWarrantyLimit = investmentValue;
}
}
ItemCalculation itemCalculation = ItemCalculation.builder()
.amountOfItems(amountOfItems)
.averagePrice(priseSum / amountOfItems)
.averageInvestmentValue(investmentValueSum / amountOfItems)
.highestWarrantyLimit(highestWarrantyLimit)
// ...
.build();
Run Code Online (Sandbox Code Playgroud)
添加流 API 是为了提供处理数据元素序列的库支持,这对于您的情况来说非常正确。但是,流为数据元素强加了一个通用管道,这对于您的情况来说并不正确,并使管道看起来像:
itemList.stream()
.collect(toItemCalculation());
Run Code Online (Sandbox Code Playgroud)
这不是很合理,除非您要在多线程模式下使用它。在这种情况下,使用自定义收集器的解决方案将是更好的选择,因为用于组合逻辑的脚手架代码已经内置。
| 归档时间: |
|
| 查看次数: |
147 次 |
| 最近记录: |