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

Java中使用TreeSet存储自定义pair类的元素插入异常问题

TreeSet使用自定义Comparator时的元素唯一性判断问题

核心原因:TreeSet的元素唯一性由Comparator决定

当给TreeSet传入自定义Comparator时,TreeSet会完全依赖这个比较器的返回值判断元素是否重复——只要compare(a,b)返回0,就认为a和b是同一个元素,不会重复插入,完全忽略你重写的equals和hashCode方法。

第一种Comparator的问题分析

你第一个Comparator仅比较w字段:

public int compare(pair a , pair b){
    return a.w-b.w;
}

p1、p2、p3的w值都是3,所以:

  • 插入p2时,TreeSet用该比较器和已存在的p1对比,返回0,判定为重复元素,拒绝插入
  • 插入p3时,和p1对比同样返回0,也被判定为重复,拒绝插入
  • 只有p4的w是4,和p1对比返回非0值,正常插入
    最终集合里只剩p1和p4,size为2。

修改后的Comparator为什么能正常插入

修改后的Comparator依次比较w、i、j三个字段:

public int compare(pair a , pair b){
    if(a.w==b.w ){
        if(a.i==b.i)
            return a.j-b.j;
        return a.i-b.i; 
    }
    return a.w-b.w;
}

此时p1、p2、p3之间的对比结果都不会是0:

  • p1(1,3,3)和p2(1,2,3):w相同、i相同、j不同,返回3-2=1≠0
  • p1和p3(2,2,3):w相同、i不同,返回1-2=-1≠0
  • p2和p3:w相同、i不同,返回1-2=-1≠0
    TreeSet判定这三个都是不同元素,加上p4,四个元素全部被插入。

纠正你的误解

HashSet这类基于哈希表的集合才会用equals和hashCode判断元素重复,但TreeSet是基于红黑树的有序集合,它的元素唯一性规则是:

  • 如果元素实现Comparable接口,用compareTo方法返回0判定相等
  • 如果传入自定义Comparator,就用compare方法返回0判定相等
    此时equals和hashCode的实现不会影响TreeSet的插入逻辑(不过从Java规范来说,建议让equals的结果和比较器的判断一致,避免出现集合逻辑矛盾)。

额外代码问题提示

你的pair类里的hashCode方法定义错误,正确的hashCode方法应为无参,且需添加@Override注解:

@Override
public int hashCode(){
    return Objects.hash(i,j,w);
}

这个错误不影响当前TreeSet的问题,但会导致将pair对象放入HashSet这类集合时出现异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 18:47:41