Java移除列表中属性重复元素:保留每组最后一个实例
解决方案
核心思路
要实现保留每组firstName+lastName重复的最后一个元素、且过滤后列表顺序与原列表一致,核心逻辑是:
- 用
firstName和lastName的组合作为重复判断的唯一标识(key) - 从后往前遍历原列表,优先保留最后出现的元素,再反转结果恢复原顺序
- 将过滤后的列表更新回
SampleClass实例
代码实现
方式一:循环遍历(直观易懂,适合新手)
import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; // 1. 获取原列表 List<ValueObject> originalValues = listWithDuplicates.getValues(); Set<String> seenKeys = new HashSet<>(); List<ValueObject> filteredValues = new ArrayList<>(); // 2. 从后往前遍历,保留每个key的最后一个元素 for (int i = originalValues.size() - 1; i >= 0; i--) { ValueObject current = originalValues.get(i); // 用分隔符避免拼接冲突(比如firstName含特殊字符的情况) String key = current.getFirstName() + "###" + current.getLastName(); if (!seenKeys.contains(key)) { seenKeys.add(key); filteredValues.add(current); } } // 3. 反转列表恢复原顺序 Collections.reverse(filteredValues); // 4. 更新回SampleClass实例 listWithDuplicates.setValues(filteredValues);
方式二:用Entry作为key(更可靠,避免字符串拼接冲突)
如果担心字符串拼接导致的key误判(比如特殊字符重叠),可以用AbstractMap.SimpleEntry封装两个字段作为判断key:
import java.util.AbstractMap; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; List<ValueObject> originalValues = listWithDuplicates.getValues(); Set<AbstractMap.SimpleEntry<String, String>> seenKeys = new HashSet<>(); List<ValueObject> filteredValues = new ArrayList<>(); for (int i = originalValues.size() - 1; i >= 0; i--) { ValueObject current = originalValues.get(i); AbstractMap.SimpleEntry<String, String> key = new AbstractMap.SimpleEntry<>(current.getFirstName(), current.getLastName()); if (!seenKeys.contains(key)) { seenKeys.add(key); filteredValues.add(current); } } Collections.reverse(filteredValues); listWithDuplicates.setValues(filteredValues);
方式三:Stream流实现(简洁但需理解逻辑)
如果想用Stream流处理,可以结合LinkedHashMap保留顺序,步骤是先反转原列表确保最后出现的元素被保留,再反转结果恢复原顺序:
import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; List<ValueObject> filteredValues = listWithDuplicates.getValues().stream() // 反转原列表,让最后出现的元素先被处理 .collect(Collectors.collectingAndThen(Collectors.toList(), lst -> { Collections.reverse(lst); return lst; })) // 用LinkedHashMap保留插入顺序,重复key时保留新值(即原列表最后出现的元素) .stream() .collect(Collectors.toMap( vo -> new AbstractMap.SimpleEntry<>(vo.getFirstName(), vo.getLastName()), vo -> vo, (oldVal, newVal) -> newVal, LinkedHashMap::new )) // 提取values并反转,恢复原列表顺序 .values() .stream() .collect(Collectors.collectingAndThen(Collectors.toList(), lst -> { Collections.reverse(lst); return lst; })); listWithDuplicates.setValues(filteredValues);
对你原有代码的补充说明
你之前只按lastName分组,现在需要把firstName和lastName组合作为分组key,比如:
// 按firstName+lastName分组,每组是该组合下的所有元素 Map<String, List<ValueObject>> grouped = listWithDuplicates.getValues().stream() .collect(Collectors.groupingBy( vo -> vo.getFirstName() + "###" + vo.getLastName() ));
但分组后还需要提取每组的最后一个元素,再按原列表顺序排列——这一步用循环的方式更直接,所以优先推荐前面的实现方式。
内容的提问来源于stack exchange,提问作者noob123
相关产品推荐
相关产品推荐

