javaStream流toMap小坑
先来show一下报错信息: java.lang.IllegalStateException: Duplicate key 13800138000 (attempted merging values BlackTelChannel(id=null, tel=13800138000, source=A, industry=null, createdAt=null, available=null) and BlackTelChannel(id=null, tel=13800138000, source=C, industry=null, createdAt=null, available=null)) 刚开始还以为是数据库数据有唯一索引。后面才发现是lambda-stream流tomap搞得鬼。分析: Collectors.toMap有3个方法,
方法1:2个参数,
toMap(Function<? super T, ? extends K> keyMapper,Function<? super T, ? extends U> valueMapper)
方法2: 3个参数,
toMap(Function<? super T, ? extends K> keyMapper,Function<? super T, ? extends U> valueMapper,BinaryOperator<U> mergeFunction)
方法3: 4个参数
toMap(Function<? super T, ? extends K> keyMapper,Function<? super T, ? extends U> valueMapper,BinaryOperator<U> mergeFunction,Supplier<M> mapFactory)
[当你希望使用特定类型的 Map(比如 LinkedHashMap、ConcurrentHashMap 等),而不是默认的 HashMap,就可以通过这个参数指定:() -> new LinkedHashMap<>()]
我是使用了3个参数就解决了问题,代码如下:
package com.funmz.vos2gaid2black;import lombok.Builder;
import lombok.Data;
import org.junit.jupiter.api.Test;import java.io.Serial;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;public class ScheduleTaskTest {@Data@Builderpublic static class BlackTelChannel implements Serializable {@Serialprivate static final long serialVersionUID = -8297608645555174167L;private String tel;private String source;}@Testpublic void testDuplicateTelToMap() {// 准备测试数据List<BlackTelChannel> oldList = new ArrayList<>();oldList.add(BlackTelChannel.builder().tel("13800138000").source("A").build());oldList.add(BlackTelChannel.builder().tel("13800138000").source("C").build()); // 与第一条 tel 重复oldList.add(BlackTelChannel.builder().tel("13900000000").source("B").build());oldList.add(BlackTelChannel.builder().tel("13700000000").source("D").build());System.out.println("oldList:" + oldList);System.out.println("oldList:" + oldList.size());// 执行转换逻辑Map<String, BlackTelChannel> oldBlackMap = oldList.stream().collect(Collectors.toMap(BlackTelChannel::getTel,Function.identity(), (existing, replacement) -> existing // existing 保留第一个遇到的 key ,replacement:最后一个));System.out.println("oldBlackMap = " + oldBlackMap);System.out.println("oldBlackMap = " + oldBlackMap.size());}
}