Java 8中过滤List<Map>:基于name属性去重并保留最后一项
嘿,这个需求我之前也帮不少人解决过,其实实现起来挺简单的,给你分享两种实用的方法,刚好覆盖不同的Java版本场景~
方法一:Java 8+ 用Stream结合LinkedHashMap(推荐)
如果你的项目已经用上Java 8及以上版本,这种方法最简洁,而且能完美保持原List中最后出现元素的顺序。核心思路是用Collectors.toMap把List转成Map,指定重复键时保留后面的元素,再把Map的values转回List就行。
import java.util.*; import java.util.stream.Collectors; public class ListMapProcessor { public static void main(String[] args) { // 模拟你的原始List数据 List<Map<String, String>> originalList = new ArrayList<>(); originalList.add(Map.of("name", "abc", "desc", "第一次出现abc")); originalList.add(Map.of("name", "def", "desc", "唯一的def")); originalList.add(Map.of("name", "abc", "desc", "最后一次出现abc")); // 核心处理逻辑 List<Map<String, String>> processedList = originalList.stream() .collect(Collectors.toMap( map -> map.get("name"), // 以name作为去重的键 map -> map, // 保留当前Map作为值 (oldMap, newMap) -> newMap, // 重复时用后面的Map覆盖前面的 LinkedHashMap::new // 用LinkedHashMap保证顺序和最后出现的一致 )) .values() .stream() .collect(Collectors.toList()); // 验证结果 processedList.forEach(System.out::println); // 输出:{name=def, desc=唯一的def}, {name=abc, desc=最后一次出现abc} } }
这段代码里,Collectors.toMap的第三个参数是关键——它定义了当键重复时的合并规则,我们直接返回新的(后面出现的)Map,就能自动保留每个name对应的最后一个元素。而LinkedHashMap则保证了结果List的顺序和原List中元素最后出现的顺序一致,不会打乱顺序。
方法二:传统循环遍历(适配Java 8之前版本)
如果你的项目还在使用Java 7及更早的版本,用传统循环的方式更稳妥,逻辑也很直观:用一个临时Map来记录每个name对应的最新Map,遍历原List时不断更新这个临时Map,最后把临时Map的values转成List即可。
import java.util.*; public class ListMapProcessor { public static void main(String[] args) { List<Map<String, String>> originalList = new ArrayList<>(); originalList.add(Map.of("name", "abc", "desc", "第一次出现abc")); originalList.add(Map.of("name", "def", "desc", "唯一的def")); originalList.add(Map.of("name", "abc", "desc", "最后一次出现abc")); // 用LinkedHashMap保证顺序 Map<String, Map<String, String>> tempMap = new LinkedHashMap<>(); for (Map<String, String> currentMap : originalList) { String name = currentMap.get("name"); // 直接put,后面的Map会自动覆盖前面同name的Map tempMap.put(name, currentMap); } // 把临时Map的values转成结果List List<Map<String, String>> processedList = new ArrayList<>(tempMap.values()); processedList.forEach(System.out::println); // 输出和上面方法完全一致 } }
几个需要注意的小细节
- 要确保原始List里的每个Map都包含
name键,如果有Map没有name,map.get("name")会返回null,这时候多个无name的Map会被合并成最后一个出现的那个。如果需要过滤掉无name的Map,可以在遍历/流处理时加个判断,比如filter(map -> map.containsKey("name"))。 - 如果不需要保持结果的顺序,把LinkedHashMap换成普通HashMap也可以,但大多数场景下我们都希望结果顺序和原List中最后出现的顺序一致,所以LinkedHashMap是更好的选择。
内容的提问来源于stack exchange,提问作者chasse
相关产品推荐
相关产品推荐

