簡體   English   中英

無法應用合並 function 以轉換以在 Stream output 上設置

[英]Unable to apply Merge function to convert to get Set on a Stream output

這是一個示例源數據結構,用於簡化我的場景的問題案例數據。 這個 Map 對於不同的代碼有重復的描述。

Map<Integer, String> descriptionsByCode = new HashMap();
descriptionsByCode.put(1, "description 1");
descriptionsByCode.put(2, "description 2");
descriptionsByCode.put(4, "description 3");
descriptionsByCode.put(5, "description 4");
descriptionsByCode.put(6, "description 5");
descriptionsByCode.put(7, "description 5");
descriptionsByCode.put(8, "description 5");
descriptionsByCode.put(9, "description 2");
descriptionsByCode.put(10, "description 2");
descriptionsByCode.put(11, "description 3");
descriptionsByCode.put(12, "description 4");
descriptionsByCode.put(13, "description 1");
descriptionsByCode.put(14, "description 6");
descriptionsByCode.put(15, "description 8");

我也有一個復雜的業務 object,但為了簡單起見,我們假設有一個只有 2 個字段的 object。

@Data
@AllArgsConstructor
class StatusCounts {
    private String description;
    private Map<Integer, Integer> someIemCountByStatusCode; //defaults to zero for our example
}

如果,我想通過描述獲得StatusCount object 的 map。 我可以輕松擁有它。 下面是一個工作代碼,在這里添加以集中解決之后提到的主要問題

     Map<String, StatusCounts> statusCountsByDescription
            = descriptionsByCode
            .entrySet()
            .stream()
            .collect(Collectors.toMap(
                    e -> e.getValue(),  //key function
                    e -> new StatusCounts(e.getValue(),   //value function 
                            Collections.singletonMap(e.getKey(), 0)),
                    (e, v) ->  // merge function for collision 
                    { // is there a better way to write below code ? 
                        Map m = new HashMap();
                        m.putAll(e.getItemCountByStatusCode());
                        m.putAll(v.getItemCountByStatusCode());
                        e.setItemCountByStatusCode(m);
                        return e;
                    }
            ));

上面的代碼不干凈,但運行良好。 我真正想要的是一個 Set 而不是 Map

我無法在reducecollect函數中找到一種方法來提供collision detection處理(例如在Collectors.toMap的情況下合並 function )。

合並器 function 在減少或收集中均不適用於碰撞。
Collectors.toSet甚至不接受任何參數。 所以我雖然可以在accumulator中編寫碰撞檢測處理,以防reduce或 in 或Biconsumer以防collect 所以我在下面嘗試使用collect & BiConsumer但這一個是不可編譯的, reduce也發生了同樣的情況

Set<StatusCounts> statusCounts
            = descriptionsByCode
            .entrySet()
            .stream()
            .collect(() -> new HashSet<StatusCounts>(),
                    (set, entry) -> {
                        Optional<StatusCounts> statusCount
                                = findStatusCountWithSameDescription(set, entry.getValue());

                        if (statusCount.isPresent()) {
                            statusCount.get()
                                        .getItemCountByStatusCode()
                                        .put(entry.getKey(), 0);
                        } else {
                            set.add(new StatusCounts(
                                    entry.getValue(),
                                    Collections.singletonMap(entry.getKey(), 0)));
                        }
                        return set;
                    }
            );



private static Optional<StatusCounts> findStatusCountWithSameDescription
       (HashSet<StatusCounts> set, String description) {
        return set.stream()
                  .filter(e -> e.getDescription()
                                .equalsIgnoreCase(description))
                  .findFirst();
    }

這是編譯錯誤

Cannot resolve method 'collect(<lambda expression>, <lambda expression>)'

你可以使用Collectors.groupingBy來解決這個問題:

Map<String, Set<Integer>> map 
    = descMap.entrySet()
             .stream()
             .collect(Collectors.groupingBy(Entry::getValue, 
                                            Collectors.mapping(Entry::getKey, Collectors.toSet())));                                       

在這里,將以描述為鍵生成 map。 Collectors.mapping將每個條目映射到狀態碼,然后將它們組合成一個Set

現在,如果需要,您可以將其轉換為Map<String, StatusCounts>為:

return map.entrySet()
          .stream()
          .collect(Collectors.toMap(Entry::getKey, 
                                    entry -> new StatusCounts(entry.getKey(), entry.getValue())));

暫無
暫無

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

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