簡體   English   中英

Java 8 Stream從對象映射創建對象

[英]Java 8 Stream Create an Object from Map of Objects

我剛開始通過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_amountlast_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。

任何幫助將非常感激。 謝謝。

編輯1-為簡單起見,請考慮lastMarketingRegion對於折扣代碼具有相同的值。 我也試圖通過圖表來解釋它- 在此處輸入圖片說明

來自評論

當您為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映射,所以我選擇它的區域。

如果您通過添加otherBillsprepaid構造列表,那么它將具有不同的輸出。

依靠相遇順序使這不是一個很好的解決方案 (如果您假設我們在處理完第一個地圖后處理了第二個地圖中的條目,為什么要首先合並它們?)

查看我使用Map.merge 其他答案

如果只有兩個地圖,則可以使用Map.merge ,而不是使用基於流的解決方案(我的其他答案 )。

在這里,我們制作了prepaid地圖的副本。 然后,我們遍歷otherBills地圖。 對於每個鍵

  1. 如果映射不存在,則將其添加到地圖(結果地圖)
  2. 如果映射已經存在,我們將構造一個新的Discount對象,其金額為地圖中已存在的Discount對象(一個來自prepaid )和當前Discount對象(一個來自otherBill )的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())));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM