Exception in thread "main" java.lang.IllegalStateException: Duplicate key 1


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
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonDTO implements Serializable {
?
private String key;
?
private String value;
}

 

问题解决

解决办法:使用重载方法,多传入一个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.
    *
    *

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.
    *
    *

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:
    *

{@code
    * Map phoneBook
    *   = people.stream().collect(
    *     toMap(Person::getName,
    *           Person::getAddress,
    *           (s, a) -> s + ", " + a));
    * }

    *
    * @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 the type of the input elements
    * @param the output type of the key mapping function
    * @param 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:Exception in thread "main" java.lang.IllegalStateException

文档参考地址2: