为了账号安全,请及时绑定邮箱和手机立即绑定

Java 8 Stream 从对象映射创建对象

Java 8 Stream 从对象映射创建对象

白猪掌柜的 2021-08-25 15:05:03
我刚开始通过 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 对象的集合,其中的金额是来自 otherBills 的相同键和区域的总金额。任何帮助将不胜感激。谢谢。
查看完整描述

2 回答

?
蓝山帝景

TA贡献1843条经验 获得超7个赞

来自评论


当您有 LUCKY10 的“M2”和“M5”条目时,为什么您期望“LUCKY10”-“M5”?


因为 otherBills 比预付更优先


您可以Collectors.toMap为此使用。它的最后一个参数是mergeFunction合并地图中具有相同字符串键的两个折扣。


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,那么这将有不同的输出。


依靠遭遇顺序使这不是一个很好的解决方案。(如果您假设我们在处理第一个地图后处理第二个地图中的条目,为什么首先合并它们?)



查看完整回答
反对 回复 2021-08-25
?
临摹微笑

TA贡献1982条经验 获得超2个赞

如果您只有两张地图,那么与其使用基于流的解决方案,您可以使用Map.merge它。

在这里,我们制作prepaid地图的副本。然后我们遍历otherBills地图。对于每个键

  1. 如果映射不存在,则将其添加到映射(结果映射)中

  2. 如果映射已经存在,我们构造一个新Discount对象,其数量是映射中已经存在的 Discount 对象(来自 的prepaid那个)和当前的 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())));


查看完整回答
反对 回复 2021-08-25
  • 2 回答
  • 0 关注
  • 430 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信