當您省略合併函數時,合併函數沒有機會獲得密鑰,這是內置函數具有的相同問題。
的解決方案是使用不同的toMap
實現,它不依賴於Map.merge
:
public static <T, K, V> Collector<T, ?, Map<K,V>>
toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends V> valueMapper) {
return Collector.of(HashMap::new,
(m, t) -> {
K k = keyMapper.apply(t);
V v = Objects.requireNonNull(valueMapper.apply(t));
if(m.putIfAbsent(k, v) != null) throw duplicateKey(k, m.get(k), v);
},
(m1, m2) -> {
m2.forEach((k,v) -> {
if(m1.putIfAbsent(k, v)!=null) throw duplicateKey(k, m1.get(k), v);
});
return m1;
});
}
private static IllegalStateException duplicateKey(Object k, Object v1, Object v2) {
return new IllegalStateException("Duplicate key "+k+" (values "+v1+" and "+v2+')');
}
(這基本上就是Java的9的實施toMap
沒有合併功能將做)
因此,您需要在代碼中執行的操作是重定向toMap
調用並省略合併功能:
String keyvalp = "test=one\ntest2=two\ntest2=three";
Map<String, String> map = Pattern.compile("\n")
.splitAsStream(keyvalp)
.map(entry -> entry.split("="))
.collect(toMap(split -> split[0], split -> split[1]));
(或ContainingClass.toMap
如果既沒有在同一個班,也不是一成不變進口)< \ SUP>
的收集器支持像原來toMap
收集器的並行處理,雖然它不太可能在這裏得到並行處理的好處即使有更多的元素需要處理。
如果,如果我讓你正確,你只需要任意選取,舊或新的價值,基於實際鍵合併功能,您可以用鑰匙Predicate
這樣
public static <T, K, V> Collector<T, ?, Map<K,V>>
toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends V> valueMapper,
Predicate<? super K> useOlder) {
return Collector.of(HashMap::new,
(m, t) -> {
K k = keyMapper.apply(t);
m.merge(k, valueMapper.apply(t), (a,b) -> useOlder.test(k)? a: b);
},
(m1, m2) -> {
m2.forEach((k,v) -> m1.merge(k, v, (a,b) -> useOlder.test(k)? a: b));
return m1;
});
}
做
Map<String, String> map = Pattern.compile("\n")
.splitAsStream(keyvalp)
.map(entry -> entry.split("="))
.collect(toMap(split -> split[0], split -> split[1], key -> condition));
有幾種方式來定製這個收集器...
你可以過濾合併後的值,真的需要在合併時過濾它們嗎? –
你能舉個例子嗎?在合併過程中,我必須決定採用哪個值(o1或o2)。必須在**鍵**上做出決定。但關鍵並不總是出現兩次。只有在某些情況下,合併必須決定。 – membersound
好吧,我明白了。您可以創建單獨的Map並運行'.map(entry - > entry.split(「=」))。forEach()'並檢查每個條目是否值已在Map中。如果沒有 - 添加,否則 - 檢查決定是否替換或否。 –