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

如何精准查找两个Java List之间的内容差异?

问题根源

你当前的实现存在两个核心问题:

  1. 分词规则不合理:按\s+空格拆分时,标点会和相邻单词绑定为同一个元素,导致s2中的match.和s1中的match被判定为完全不同的元素,无法拆分出末尾的.差异。
  2. removeAll逻辑不匹配需求:该方法是无顺序的集合差集计算,只会完全删除s1中存在的元素,既不识别元素顺序,也无法提取元素内部的局部差异,只要两个元素不完全相等就会整体保留。

解决方案

根据你的需求可以选择两种实现路径:

路径1:字符级差异提取(直接得到你期望的!和.结果)

直接逐字符对比两个字符串,过滤空格后即可得到精准的差异字符:

public List<Character> getCharLevelDiff(String s1, String s2) {
    List<Character> diffs = new ArrayList<>();
    int maxLen = Math.max(s1.length(), s2.length());
    for (int i = 0; i < maxLen; i++) {
        char c1 = i < s1.length() ? s1.charAt(i) : Character.MIN_VALUE;
        char c2 = i < s2.length() ? s2.charAt(i) : Character.MIN_VALUE;
        if (c1 != c2 && !Character.isWhitespace(c2)) {
            diffs.add(c2);
        }
    }
    return diffs;
}

路径2:保留列表对比逻辑,适配顺序敏感的差异识别

如果后续需要保持按语义单元拆分对比的能力,先优化分词规则把标点拆分为独立元素,再用文本diff标准的最长公共子序列(LCS)算法做顺序敏感的差异计算:

// 优化分词:把单词、标点分别拆为独立列表元素
private List<String> splitWithPunctuation(String s) {
    List<String> tokens = new ArrayList<>();
    Matcher matcher = Pattern.compile("\\w+|[^\\w\\s]").matcher(s);
    while (matcher.find()) {
        tokens.add(matcher.group());
    }
    return tokens;
}

// 基于LCS的顺序敏感列表差异计算,返回s2相对s1的新增内容
public <T> List<T> sequenceDiff(List<T> s2, List<T> s1) {
    int n = s1.size(), m = s2.size();
    int[][] dp = new int[n + 1][m + 1];
    // 构建LCS动态规划表
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (s1.get(i - 1).equals(s2.get(j - 1))) {
                dp[i][j] = dp[i - 1][j - 1] + 1;
            } else {
                dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
            }
        }
    }
    // 回溯提取差异
    List<T> diffs = new ArrayList<>();
    int i = n, j = m;
    while (i > 0 && j > 0) {
        if (s1.get(i - 1).equals(s2.get(j - 1))) {
            i--;
            j--;
        } else if (dp[i - 1][j] > dp[i][j - 1]) {
            i--;
        } else {
            diffs.add(s2.get(j - 1));
            j--;
        }
    }
    while (j > 0) {
        diffs.add(s2.get(j - 1));
        j--;
    }
    Collections.reverse(diffs);
    return diffs;
}

调用时先用splitWithPunctuation拆分s1、s2得到两个列表,再传入sequenceDiff即可得到!和.的预期结果。


内容的提问来源于stack exchange,提问作者Beginner

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.09 21:48:04