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

Java比较无equals/hashCode类型集合如何正确校验元素基数

问题描述
  • 场景:使用未定义equals、hashCode方法的第三方类型,已自定义单元素相等判断规则:实例的data属性值一致则判定两实例相等
  • 缺陷:现有集合比较逻辑未统计元素出现次数(基数),会将[Box(1),Box(1),Box(2)]和[Box(1),Box(2),Box(2)]错误判定为相等,对应单元测试断言失败。
根因分析

原有集合比较逻辑遍历第一个集合的元素时,只要在第二个集合中找到任意一个匹配项就判定匹配,不会标记或移除已经被匹配过的元素,导致多个重复元素会重复匹配到第二个集合中的同一个元素,无法校验元素的出现次数。

修正实现

由于第三方类未实现hashCode方法,无法基于哈希结构做元素频次统计,因此采用拷贝集合+匹配移除的方案,替换原有集合重载的equals方法即可:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.function.BiPredicate;

static <T> boolean equals(Collection<T> collection1, Collection<T> collection2, BiPredicate<T, T> equals) {
    if (collection1.size() != collection2.size()) {
        return false;
    }

    // 拷贝待匹配集合,避免修改原始入参产生副作用
    List<T> pendingMatch = new ArrayList<>(collection2);

    for (T t1 : collection1) {
        Iterator<T> matchIterator = pendingMatch.iterator();
        boolean isMatched = false;
        while (matchIterator.hasNext()) {
            T t2 = matchIterator.next();
            if (equals.test(t1, t2)) {
                // 匹配成功后移除该元素,防止后续元素重复匹配
                matchIterator.remove();
                isMatched = true;
                break;
            }
        }
        if (!isMatched) {
            return false;
        }
    }

    return pendingMatch.isEmpty();
}
逻辑验证

针对原失败测试用例[Box(1), Box(1), Box(2)]和[Box(1), Box(2), Box(2)]:

  1. 初始待匹配列表为[Box(1), Box(2), Box(2)]
  2. 遍历第一个集合的第一个Box(1),匹配到待匹配列表中的Box(1)并移除,待匹配列表变为[Box(2), Box(2)]
  3. 遍历第一个集合的第二个Box(1),遍历待匹配列表无对应匹配项,直接返回false,符合断言预期。
    所有原有测试用例均可正常通过。

内容的提问来源于stack exchange,提问作者Jónás Balázs

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 09:22:01