我刚开始通过Java 8流API学习和实现集合。我有一堂课:
public class Discount {
int amount;
String lastMarketingRegion;
Discount (int amount, String lastMarketingRegion) {
this.amount = amount;
this.lastMarketingRegion= lastMarketingRegion;
}
public int getAmount() { return amount; }
public String getLastMarketingRegion() { return lastMarketingRegion; }
public String toString() {
return String.format("{%s,\"%s\"}", amount, lastMarketingRegion);
}
}
给出以下内容:
Map<String, Discount> prepaid = new HashMap<String, Discount>();
prepaid.put("HAPPY50", new Discount(100, "M1"));
prepaid.put("LUCKY10", new Discount(10, "M2"));
prepaid.put("FIRSTPAY", new Discount(20, "M3"));
Map<String, Discount> otherBills = new HashMap<String, Discount>();
otherBills.put("HAPPY50", new Discount(60, "M4"));
otherBills.put("LUCKY10", new Discount(7, "M5"));
otherBills.put("GOOD", new Discount(20, "M6"));
List<Map<String, Discount>> discList = new ArrayList<Map<String, Discount>>();
discList.add(prepaid);
discList.add(otherBills);
因此,基本上,我有一个Discount
地图列表,其中列出了不同付款方式的所有折扣代码。
要求是使用sum_of_amount
和last_region
创建一个具有所有付款类型的所有折扣代码的地图:
Map<String, Discount> totalDiscounts =
{LUCKY10={17, "M5"}, FIRSTPAY={20, "M3"}, HAPPY50={160, "M4"}, GOOD={20, "M6"}}
我能够得到:
Map<String, Integer> totalDiscounts =
{LUCKY10=17, FIRSTPAY=20, HAPPY50=160, GOOD=20}
通过使用以下代码:
Map<String, Integer> afterFormatting = discList.stream()
.flatMap(m -> m.entrySet().stream())
.collect(Collectors.groupingBy(Map.Entry::getKey, Collectors.summingInt(map -> map.getValue().amount)));
但是我还需要一个Discount
对象以及该区域。
我需要一个Discount对象的集合,其数量是相同键的总和,而区域是来自其他票据。
任何帮助将不胜感激。谢谢。
编辑1- 为简单起见,请考虑lastMarketingRegion对于折扣代码具有相同的值。 我还尝试通过图表进行解释-
答案 0 :(得分:3)
来自评论
为什么当LUCKY10有“ M2”和“ M5”条目时,为什么会期望“ LUCKY10”-“ M5”?
因为其他账单的优先级高于预付款
您可以为此使用Collectors.toMap
。最后一个参数是mergeFunction
,它合并了两个在地图中具有相同String键的Discounts。
Map<String, Discount> totalDiscounts = discList.stream()
.flatMap(m -> m.entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(discount1, discount2) -> new Discount(discount1.getAmount() + discount2.getAmount(),
discount2.getLastMarketingRegion())));
由于从列表中生成的流是有序的,因此discount2
折扣将是otherBills
映射中的那个,因此,我选择了它的区域
如果您先添加otherBills
后再加上prepaid
来构建列表,则输出将有所不同。
依靠相遇顺序将其设为非最佳解决方案。 (如果您假设我们在处理完第一个地图后处理了第二个地图中的条目,为什么要首先合并它们?)
查看我使用Map.merge
的{{3}}
答案 1 :(得分:2)
如果只有两个地图,则可以使用Map.merge
来代替基于流的解决方案(我的other answer)。
在这里,我们制作了prepaid
地图的副本。然后,我们遍历otherBills
映射。对于每个键
Discount
对象,其数量是地图中已经存在的Discount对象(来自prepaid
的Discount对象和当前Discount对象的总和) (来自otherBill
的那个)。它从otherBill
映射中获取Discount对象的区域。Map<String, Discount> result = new HashMap<>(prepaid);
otherBills.forEach((k, v) -> result.merge(k, v, (discountFromPrepaid, discountFromOtherBill) ->
new Discount(discountFromPrepaid.getAmount() + discountFromOtherBill.getAmount(),
discountFromOtherBill.getLastMarketingRegion())));