java.lang.IllegalStateException: Duplicate key
阿新 • • 發佈:2020-12-12
文章目錄
java.lang.IllegalStateException: Duplicate key
// list轉map key重複
java.lang.IllegalStateException: Duplicate key DealerImageInfo
出現原因
當使用java.util.Collection
的stream()
方法將集合轉為Map
時,如果key
有重複就會丟擲此異常。
//將List型別的entityList轉為entityMap,Entity的id欄位作為key,entity物件為value
//Entity::getId:獲取Entity的id欄位
//Function.identity()等同於x->x,將輸入作為輸出,即將遍歷的物件最為value
Map<Long, Entity> entityMap= entityList.stream().collect(Collectors.toMap(Entity::getId, Function.identity()));
此時如果entityList
中entity
id
有重複,就會丟擲此異常;
解決方法
- 保證待轉化的List中各物件作為key的欄位不重複(業務方式處理,不做介紹);
- 使用toMap的過載方法。
Map<Long, Entity> entityMap= entityList.stream().collect(Collectors.toMap(Entity::getId, Function.identity(), (var1, var2) -> var1));
這種方式是toMap()
方法新加一個引數,該引數是重複資料的處理規則。示例中使用這種方式是保留第一條資料,讀者也可以根據需求寫第三個引數。
自此異常處理完畢,下面寫一些toMap的過載方法。
番外:toMap的過載方法
toMap
方法的三種過載:
toMap(Function<? super T, ? extends K>, Function<? super T, ? extends U>):Collector<T, ?, Map<K,U>>
toMap(Function<? super T, ? extends K>, Function<? super T, ? extends U>, BinaryOperator<U>):Collector<T, ?, Map<K,U>>
toMap(Function<? super T, ? extends K>, Function<? super T, ? extends U>, BinaryOperator<U>, Supplier<M>):Collector<T, ?, M>
這三個過載方法最終執行方法是最後一個,前兩個都是加入預設引數後呼叫第三個方法;
方法引數含義如下:
- 獲取
Map
的Key
- 獲取
Map
的value
key
重複時合併規則- 最終的返回型別 (不傳時預設返回
Map
型別)
第一個方法第3個引數預設置為throwingMerger()
方法,表示有重複時丟擲異常,就是題目中的異常
第二個方法可以自定義第3個引數,定義為(entity1,entity2) -> entity1
,表示保留第一個資料
原始碼:
// 只有兩個引數的toMap
// 這個方法預設的重複資料處理規則是呼叫throwingMerger()方法
// 返回的Map是HashMap
public static <T, K, U>
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper) {
return toMap(keyMapper, valueMapper, throwingMerger(), HashMap::new);
}
// throwingMerger方法對重複資料直接丟擲異常,這個異常就是我們見到的異常
private static <T> BinaryOperator<T> throwingMerger() {
return (u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); };
}
// 三個引數的方法可以指定重複資料的處理規則
// 返回的Map是HashMap
public static <T, K, U>
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction) {
return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
}
public static <T, K, U, M extends Map<K, U>>
Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction,
Supplier<M> mapSupplier) {
BiConsumer<M, T> accumulator
= (map, element) -> map.merge(keyMapper.apply(element),
valueMapper.apply(element), mergeFunction);
return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);
}