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

Java比对二维Comparable数组集合时如何正确计算含重复值的公共元素

多数组公共元素统计实现问题修正

原代码核心缺陷

  • 使用==比较Comparable类型对象,本质是引用地址判等而非值比较,对非基础包装类的元素会直接产生逻辑错误;即使对Integer、Long这类缓存范围的包装类型,超出缓存区间的比较结果也会失效
  • 引入commonList.contains()判断是否允许添加元素的逻辑,完全偏离了「按频次统计公共重复元素」的需求:公共重复元素的合法出现次数,等于该元素在所有输入数组中出现次数的最小值,而非只要出现过一次就禁止后续添加
  • 每轮数组比对时没有新建临时列表存储当前轮次的交集结果,直接复用跨轮次的公共列表做累加,导致多轮比对时元素被重复计数,出现三个数组都仅含单个4却返回两个4的错误结果

正确实现路径

  • 对每个输入数组预先排序,为双指针求多集交集做准备
  • 每轮比对时,将上一轮得到的公共元素序列,与下一个输入数组求多集交集:通过双指针同步遍历两个已排序序列,按元素值大小移动指针,元素相等时就记录到临时交集列表,指针同步后移,完全按实际最小频次计数,不做去重处理
  • 全部数组比对完成后,最终的交集列表就是所有数组的公共元素集合,天然支持重复值的准确统计

修正后代码实现

import java.util.Arrays;
import java.util.ArrayList;

public class CommonElements {
    private int comparisons = 0;

    public Comparable<?>[] findCommonElements(Comparable<?>[][] collections) {
        // 空集合兜底
        if (collections == null || collections.length == 0) {
            return new Comparable[0];
        }
        // 单数组场景直接返回
        if (collections.length == 1) {
            return collections[0];
        }

        // 初始公共序列为第一个数组,预先排序
        Comparable<?>[] currentCommon = collections[0];
        Arrays.sort(currentCommon);

        // 逐个数组求多集交集
        for (int i = 1; i < collections.length; i++) {
            Comparable<?>[] nextArr = collections[i];
            Arrays.sort(nextArr);
            ArrayList<Comparable<?>> tempIntersection = new ArrayList<>();
            
            int p1 = 0, p2 = 0;
            // 双指针遍历两个已排序序列求交集
            while (p1 < currentCommon.length && p2 < nextArr.length) {
                Comparable<?> e1 = currentCommon[p1];
                Comparable<?> e2 = nextArr[p2];
                comparisons++;
                
                @SuppressWarnings("unchecked")
                int cmp = ((Comparable<Object>) e1).compareTo(e2);
                if (cmp == 0) {
                    // 元素相等则记录,双指针同步后移,按频次计数
                    tempIntersection.add(e1);
                    p1++;
                    p2++;
                } else if (cmp < 0) {
                    // 当前公共序列元素更小,移动指针1
                    p1++;
                } else {
                    // 待比对数组元素更小,移动指针2
                    p2++;
                }
            }
            
            // 交集为空则无公共元素,提前返回
            if (tempIntersection.isEmpty()) {
                return new Comparable[0];
            }
            // 更新下一轮比对的公共序列为当前交集结果
            currentCommon = tempIntersection.toArray(new Comparable[0]);
        }
        return currentCommon;
    }

    public int getComparisons() {
        return comparisons;
    }
}

验证效果

  • 输入集合{{1,1,1,1}, {1,1,1,3}, {1,1,1,5}},第一轮交集从两个数组中统计得到3个公共1,第二轮与第三个数组比对仍保留3个1,最终输出{1,1,1},符合重复元素统计要求
  • 输入集合{{4,7,9}, {4,5,6}, {1,3,4}},第一轮交集从两个数组中统计得到1个公共4,第二轮与第三个数组比对仍保留1个4,最终输出{4},不会出现重复计数错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.30 10:15:03