如何将List<Object>转为Map<String, List<Object>>并按元素属性去重?
解决List转Map<String, List- >并去重的问题
嘿,这个需求用Java 8+的Stream API就能优雅搞定!结合你给出的RawItem和Item类,咱们分两步走:先对RawItem列表去重,再按category分组并转换为Item列表。
前提准备:给实体类添上必要方法
首先,RawItem和Item需要有构造器和getter方法(Stream要访问属性),如果要简化去重逻辑,还可以重写equals()和hashCode():
import java.util.Objects; class RawItem { private String category; private int code; private String name; // 构造器 public RawItem(String category, int code, String name) { this.category = category; this.code = code; this.name = name; } // Getter方法 public String getCategory() { return category; } public int getCode() { return code; } public String getName() { return name; } // 可选:重写equals和hashCode,用于distinct()去重 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; RawItem rawItem = (RawItem) o; return code == rawItem.code && Objects.equals(category, rawItem.category) && Objects.equals(name, rawItem.name); } @Override public int hashCode() { return Objects.hash(category, code, name); } } class Item { private int code; private String name; public Item(int code, String name) { this.code = code; this.name = name; } // 可选:toString方便查看结果 @Override public String toString() { return "Item{code=" + code + ", name='" + name + "'}"; } }
方案1:修改RawItem类,用distinct()去重(简洁版)
如果能修改RawItem的代码,重写equals()和hashCode()后,直接用distinct()就能轻松去重,再分组转换:
import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { List<RawItem> rawItems = List.of( new RawItem("a", 1, "item1"), new RawItem("a", 1, "item1"), new RawItem("a", 2, "item2"), new RawItem("b", 1, "item1"), new RawItem("b", 1, "item1") ); // 一步到位:去重 + 分组 + 转换 Map<String, List<Item>> resultMap = rawItems.stream() .distinct() // 依赖重写的equals和hashCode去重 .collect(Collectors.groupingBy( RawItem::getCategory, // 按category作为Map的key Collectors.mapping( raw -> new Item(raw.getCode(), raw.getName()), // 转成Item Collectors.toList() ) )); // 打印验证结果 resultMap.forEach((cat, items) -> { System.out.println("分类:" + cat); items.forEach(System.out::println); }); } }
方案2:不修改RawItem类,用toMap去重(灵活版)
如果不能修改RawItem的源码,咱们可以用Collectors.toMap生成临时Map来实现去重,避免重写equals/hashCode:
import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { List<RawItem> rawItems = List.of( new RawItem("a", 1, "item1"), new RawItem("a", 1, "item1"), new RawItem("a", 2, "item2"), new RawItem("b", 1, "item1"), new RawItem("b", 1, "item1") ); // 第一步:去重——用category+code+name拼接成唯一key,重复时保留第一个元素 List<RawItem> uniqueRawItems = rawItems.stream() .collect(Collectors.toMap( // 生成唯一标识key:category_code_name item -> item.getCategory() + "_" + item.getCode() + "_" + item.getName(), item -> item, // value是原RawItem (existing, newItem) -> existing // 重复key时保留已有元素 )) .values() // 提取去重后的RawItem集合 .stream() .collect(Collectors.toList()); // 第二步:分组并转换为Item列表 Map<String, List<Item>> resultMap = uniqueRawItems.stream() .collect(Collectors.groupingBy( RawItem::getCategory, Collectors.mapping( raw -> new Item(raw.getCode(), raw.getName()), Collectors.toList() ) )); // 打印结果 resultMap.forEach((cat, items) -> { System.out.println("分类:" + cat); items.forEach(System.out::println); }); } }
结果验证
两种方案运行后都会输出:
分类:a Item{code=1, name='item1'} Item{code=2, name='item2'} 分类:b Item{code=1, name='item1'}
完全符合你的需求:按category分组,每个分组里的Item没有重复项。
内容的提问来源于stack exchange,提问作者Wuaner
相关产品推荐
相关产品推荐

