使用Collectors.toMap处理重复元素时获取被丢弃的完整对象
使用Collectors.toMap处理重复元素时获取被丢弃的完整对象
嘿,这个问题我之前也碰到过!默认的Collectors.toMap里,你把Item::getName作为value mapper,所以merge函数里只能拿到两个名字字符串,自然拿不到完整的Item对象啦。要解决这个问题,其实很简单,咱们换个思路——先把整个Item对象作为value存入Map,之后如果需要Map<Integer, String>的话再转换就行,这样merge函数里就能直接拿到被替换的完整对象了。
给你改好的代码示例:
import java.util.*; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { // 示例列表,包含重复key的元素 List<Item> items = Arrays.asList( new Item(1, "Item A"), new Item(2, "Item B"), new Item(1, "Item C"), // 重复key的元素 new Item(3, "Item D") ); // 第一步:先把完整的Item对象作为value存入Map,这样merge时能拿到整个对象 Map<Integer, Item> tempItemMap = items.stream() .collect(Collectors.toMap( Item::getId, // 还是用id作为key item -> item, // 这里直接返回Item本身,而不是提取name (existingItem, incomingItem) -> { // 现在可以直接操作完整的Item对象了! System.out.println("发现重复key:" + incomingItem.getId()); System.out.println("被丢弃的对象:" + existingItem); System.out.println("保留的对象:" + incomingItem); return incomingItem; // 按照你的需求保留新传入的对象 } )); // 如果需要原来的Map<Integer, String>格式,再做一次转换即可 Map<Integer, String> itemMap = tempItemMap.entrySet().stream() .collect(Collectors.toMap( Map.Entry::getKey, entry -> entry.getValue().getName() )); // 打印最终结果 System.out.println("最终结果Map:" + itemMap); } } class Item { private final int id; private final String name; public Item(int id, String name) { this.id = id; this.name = name; } public int getId() { return id; } public String getName() { return name; } @Override public String toString() { return "Item{id=" + id + ", name='" + name + "'}"; } }
你看,核心改动就是把value mapper从Item::getName改成了item -> item,这样merge函数的参数就变成了两个完整的Item对象,想打印id、name或者整个对象都完全没问题。如果最后还是需要原来的Map<Integer, String>格式,只需要再用一次stream把每个Entry里的Item对象提取出name就行,步骤很清晰。
另外,如果你需要把所有被丢弃的对象统一收集起来,也可以提前定义一个集合,在merge函数里把existingItem加进去,比如:
List<Item> discardedItems = new ArrayList<>(); // 然后在merge函数里: discardedItems.add(existingItem);
这样后续还能对被丢弃的对象做其他处理,非常灵活。
备注:内容来源于stack exchange,提问作者Beginner
相关产品推荐
相关产品推荐

