先来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
@Builder
public static class BlackTelChannel implements Serializable {
@Serial
private static final long serialVersionUID = -8297608645555174167L;
private String tel;
private String source;
}
@Test
public 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());
}
}