[英]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
我無法在reduce
或collect
函數中找到一種方法來提供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.