Exception in thread "main" java.lang.IllegalStateException: Duplicate key 1
问题描述
原因:key重复导致的异常
错误di代码示例
public class TestCode {
public static void main(String[] args) {
List<CommonDTO> list = new ArrayList<>();
list.add( new CommonDTO(null,"2"));
list.add( new CommonDTO("1","1"));
list.add( new CommonDTO("2","3"));
list.add( new CommonDTO("1","4"));
//key重复导致异常
Map<String, CommonDTO> map = list.stream().collect(Collectors.toMap(CommonDTO::getKey, Function.identity()));
for (Map.Entry<String, CommonDTO> entry : map.entrySet()) {
System.out.println(entry);
}
}
}
/**
* 公共的数据对象
* @author lyn
*/
问题解决
解决办法:使用重载方法,多传入一个merge function来处理冲突
代码示例
Map<String, CommonDTO> map = list.stream().collect(Collectors.toMap(CommonDTO::getKey, Function.identity(), (s, a) -> a));
格式如上,s,a变量名可以随意起,如果->后是s,则保留最开始的,如果是a,则保留最后的
源码:
/**
* Returns a {@code Collector} that accumulates elements into a
* {@code Map} whose keys and values are the result of applying the provided
* mapping functions to the input elements.
*
* <p>If the mapped
* keys contain duplicates (according to {@link Object#equals(Object)}),
* the value mapping function is applied to each equal element, and the
* results are merged using the provided merging function.
*
* <p>There are no guarantees on the type, mutability, serializability,
* or thread-safety of the {@code Map} returned.
*
* @apiNote
* There are multiple ways to deal with collisions between multiple elements
* mapping to the same key. The other forms of {@code toMap} simply use
* a merge function that throws unconditionally, but you can easily write
* more flexible merge policies. For example, if you have a stream
* of {@code Person}, and you want to produce a "phone book" mapping name to
* address, but it is possible that two persons have the same name, you can
* do as follows to gracefully deal with these collisions, and produce a
* {@code Map} mapping names to a concatenated list of addresses:
* <pre>{@code
* Map<String, String> phoneBook
* = people.stream().collect(
* toMap(Person::getName,
* Person::getAddress,
* (s, a) -> s + ", " + a));
* }</pre>
*
* @implNote
* The returned {@code Collector} is not concurrent. For parallel stream
* pipelines, the {@code combiner} function operates by merging the keys
* from one map into another, which can be an expensive operation. If it is
* not required that results are merged into the {@code Map} in encounter
* order, using {@link #toConcurrentMap(Function, Function, BinaryOperator)}
* may offer better parallel performance.
*
* @param <T> the type of the input elements
* @param <K> the output type of the key mapping function
* @param <U> the output type of the value mapping function
* @param keyMapper a mapping function to produce keys
* @param valueMapper a mapping function to produce values
* @param mergeFunction a merge function, used to resolve collisions between
* values associated with the same key, as supplied
* to {@link Map#merge(Object, Object, BiFunction)}
* @return a {@code Collector} which collects elements into a {@code Map}
* whose keys are the result of applying a key mapping function to the input
* elements, and whose values are the result of applying a value mapping
* function to all input elements equal to the key and combining them
* using the merge function
*
* @see #toMap(Function, Function)
* @see #toMap(Function, Function, BinaryOperator, Supplier)
* @see #toConcurrentMap(Function, Function, BinaryOperator)
*/
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);
}
文档参考地址1:
文档参考地址2:https://www.cnblogs.com/han-1034683568/p/8624447.html