You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java移除列表中属性重复元素:保留每组最后一个实例

解决方案

核心思路

要实现保留每组firstName+lastName重复的最后一个元素、且过滤后列表顺序与原列表一致,核心逻辑是:

  1. 用firstName和lastName的组合作为重复判断的唯一标识(key)
  2. 从后往前遍历原列表,优先保留最后出现的元素,再反转结果恢复原顺序
  3. 将过滤后的列表更新回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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 02:05:20