英文:
Java 8 Query - Grouping calculation based on Key with Multiple Lists of Objects
问题
我需要一些关于使用Java 8解决方案来计算总额的帮助。
假设我有3个物品对象,每个对象都包含一个(2或3个)税对象的列表。请在下面找到此对象的详细信息 -
物品 1
(列表)
税收 1 - Id-1 | 名称-A | 描述 | 金额-Rs.5 | 更多对象
税收 2 - Id-2 | 名称-B | 描述 | 金额-Rs.10 | 更多对象
税收 3 - Id-3 | 名称-C | 描述 | 金额-Rs.8 | 更多对象
物品 2
(列表)
税收 1 - Id-1 | 名称-A | 描述 | 金额-Rs.9 | 更多对象
税收 3 - Id-3 | 名称-C | 描述 | 金额-Rs.10 | 更多对象
现在,
我已经创建了一个新的对象(聚合),该对象需要根据Id进行总计
例如:上述信息应该有3个根据Id总计的聚合对象
税收-1 | 名称-A | 描述 | 金额-Rs.14
税收-2 | 名称-B | 描述 | 金额-Rs.10
税收-3 | 名称-C | 描述 | 金额-Rs.18
我能够通过循环遍历每个对象并将其添加到一个Map<String, Aggregate>
中来实现这一点。如果键已经存在,我将从聚合对象中提取金额值并将金额添加到现有金额中。如果不存在,我将创建一个新的聚合对象并将其添加到地图中,但我希望在Java 8中是否有更优化的方法来做到这一点。
全局变量 - Map<String, Aggregate> taxAggreg
for (Item item : Items) {
List<Tax> taxes = item.getTaxes;
for (Tax tax : taxes) {
createTax(Tax tax);
}
}
private void createTax(Tax tax) {
if (!taxAggreg.isEmpty() && taxAggreg.containsKey(tax.getTaxId())) {
Aggregate aggreg = taxAggreg.get(tax.getTaxId());
aggreg.setTaxAmount(aggreg.getTaxAmount().add(tax.getTaxAmount()));
taxAggreg.put(tax.getTaxId(), aggreg);
} else {
taxAggreg.put(tax.getTaxId(), new Aggregate(tax.getTaxId(), tax.getName(),
tax.getTaxAmount()));
}
}
英文:
I needed some help with a Java 8 solution to calculate totals.<br>
Suppose that I have 3 item objects and each of these objects contain a list of (2 or 3) tax objects. Please find below a detailed imaging of this object -
Item 1<br>
(List)<br>
Tax 1 - Id-1 | Name-A | Desc | Amount-Rs.5 | More objects<br>
Tax 2 - Id-2 | Name-B | Desc | Amount-Rs.10 | More objects<br>
Tax 3 - Id-3 | Name-C | Desc | Amount-Rs.8 | More objects<br>
<br>
Item 2<br>
(List)<br>
Tax 1 - Id-1 | Name-A | Desc | Amount-Rs.9 | More objects<br>
Tax 3 - Id-3 | Name-C | Desc | Amount-Rs.10 | More objects<br>
Now,<br>
I have created a new Object (Aggregate) that needs to be the total based on Id<br>
For ex: The above information should be have 3 aggregate objects with amounts summed <br>
Tax-1 | Name-A | Desc | Amount-Rs.14<br>
Tax-2 | Name-B | Desc | Amount-Rs.10<br>
Tax-2 | Name-B | Desc | Amount-Rs.18<br>
<br>
I was able to achieve this by looping through each object and adding it to a map <String Id,Object Aggregate>. If the keys existed, I would pull out the amount value from the Object Aggregate and add the amount to the existing amount. If not, I would create a new Aggregate object and add it to the map but I was hoping if there was a more optimised way to do this in Java 8<br>
Global variable - Map<String, Aggregate> taxAggreg
for (Item item: Items) {
List < Tax > taxes = item.getTaxes;
for (Tax tax: taxes) {
createTax(Tax tax);
}
}
private void createTax(Tax tax) {
if (!taxAggreg.isEmpty() && taxAggreg.containsKey(tax.getTaxId())) {
Aggregate aggreg = taxAggreg.get(tax.getTaxId());
aggreg.setTaxAmount(aggreg.getTaxAmount().add(tax.getTaxAmount()));
taxAggreg.put(tax.getTaxId(), aggreg);
} else {
taxAggreg.put(tax.getTaxId(), new Aggregate(tax.getTaxId(), tax.getName(),
tax.getTaxAmount()));
}
}
答案1
得分: 2
首先,将项目的标签列表展平,然后将Tax对象转换为Aggregate对象。然后使用Collectors.toMap
按tax id进行映射,然后合并具有相同id的tax对象。
Map<Integer, Aggregate> resMap = items.stream()
.flatMap(item -> item.getTaxes().stream())
.map(tax -> new Aggregate(tax.getTaxId(), tax.getName(), tax.getTaxAmount()))
.collect(Collectors.toMap(Tax::getTaxId, e -> e,
(a, b) -> new Aggregate(a.getTaxId(), a.getName(),
a.getTaxAmount().add(b.getTaxAmount()))));
在这里使用Collectors.toMap
按Tax::getTaxId
进行映射,这是toMap的第一个参数。下一个参数是映射的键,e -> e
表示整个Aggregate
对象作为键。最后,在合并函数的最后一个参数中,将用于将两个Aggregate
对象合并为一个Aggregate
对象,以便将相同键的所有值合并为一个Aggregate
对象。
Collectors.toMap(Tax::getTaxId, e -> e,
(a, b) -> new Aggregate(a.getTaxId(), a.getName(),
a.getTaxAmount().add(b.getTaxAmount())))
英文:
First, flat the list of tag for item, then transform the Tax object into Aggregate object. Then map by tax id using Collectors.toMap
then merge tax objects with same id.
Map<Integer, Aggregate> resMap = items.stream()
.flatMap(item -> item.getTaxes().stream())
.map(tax -> new Aggregate(tax.getTaxId(), tax.getName(), tax.getTaxAmount()))
.collect(Collectors.toMap(Tax::getTaxId, e -> e,
(a, b) -> new Aggregate(a.getTaxId(), a.getName(),
a.getTaxAmount().add(b.getTaxAmount()))));
Here using Collectors.toMap
map by Tax::getTaxId
which is the first parameter of toMap. The next one is the key of the map e -> e
for the whole Aggregate
obj as key. And finally, the last parameter in the merge function will be used for merging two Aggregate
objects into one Aggregate
object so that all values of the same key merged into one Aggregate
object
Collectors.toMap(Tax::getTaxId, e -> e,
(a, b) -> new Aggregate(a.getTaxId(), a.getName(),
a.getTaxAmount().add(b.getTaxAmount())))
答案2
得分: 0
也许类似这样的代码可以工作:
List<Aggregate> list1 = new ArrayList<Aggregate>();
List<Aggregate> list2 = new ArrayList<Aggregate>();
// 将数据添加到列表中...
// 现在为列表中每个对象创建带有其标识的映射
Map<String, Aggregate> aggregateMap1 = list1.stream().collect(Collectors.toMap(Aggregate::getId, Function.identity()));
Map<String, Aggregate> aggregateMap2 = list2.stream().collect(Collectors.toMap(Aggregate::getId, Function.identity()));
// 现在合并列表并将金额相加
List<Aggregate> result = aggregateMap1.keySet().stream().map(key -> {
Aggregate aggr1 = aggregateMap1.get(key);
Aggregate aggr2 = aggregateMap2.get(key);
if (aggr2 != null) {
aggr1.setAmount(aggr1.getAmount() + aggr2.getAmount());
}
return aggr1;
}).collect(Collectors.toList());
未经测试,还可以进行微调。
英文:
Maybe something like this could work:
List<Aggregate> list1 = new ArrayList<Aggregate>();
List<Aggregate> list2 = new ArrayList<Aggregate>();
// Add your data to lists...
// Now create maps with the identity for each object in lists
Map<String, Aggregate> aggregateMap1 = list1.stream().collect(Collectors.toMap(Aggregate::getId, Function.identity()));
Map<String, Aggregate> aggregateMap2 = list2.stream().collect(Collectors.toMap(Aggregate::geId, Function.identity()));
// Now merge lists and add the amounts together
List<Aggregate> result = aggregateMap1.keySet().forEach(key -> aggregateMap1.merge(key,
aggregateMap2.get(key),
(aggr1, aggr2) -> {
aggr1.setAmount(aggr1.getAmount() + aggr2.getAmount());
return aggr1;
})).values().stream().collect(Collectors.toList());;
Not tested. Also could be fine tuned.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论