Java TreeMap无法获取已存在的Coordenada键问题求助
Coordenada类的compareTo方法实现错误 你遇到的问题核心在于Coordenada类的compareTo方法逻辑不正确,导致TreeMap无法正确识别已插入的键。TreeMap是基于红黑树实现的有序集合,它完全依赖compareTo方法的结果来判断键的相等性和排序——当compareTo返回0时,TreeMap认为两个键是同一个;而你的equals方法逻辑和compareTo不一致,且compareTo本身的比较逻辑存在错误。
分析compareTo的错误逻辑
你的compareTo方法现在的判断顺序是:
- 如果当前x坐标大于目标x,返回1
- 如果当前y坐标大于目标y,返回1
- 如果当前x坐标小于目标x,返回-1
- 如果当前y坐标小于目标y,返回-1
- 否则返回0
这个逻辑会导致完全错误的比较结果,比如:
- 比较
Coordenada(12,2)和Coordenada(13,1)时,你的方法会因为2>1直接返回1,认为(12,2)比(13,1)大,但实际上前者的x坐标更小,应该是更小的键。 - 这种错误的排序逻辑会让
TreeMap在插入和查找时,把键放到错误的树节点位置,导致你明明看到键已插入,却用get方法找不到它。
修复方案
1. 修正compareTo方法
正确的比较逻辑应该是先比较x坐标,x相等时再比较y坐标,这样才能保证排序的一致性,同时和equals方法的逻辑匹配。修改后的代码如下:
@Override public int compareTo(Coordenada o) { // 先比较x坐标,x不同直接返回比较结果 int xComparison = Integer.compare(this.coordenada[0], o.coordenada[0]); if (xComparison != 0) { return xComparison; } // x坐标相等时,再比较y坐标 return Integer.compare(this.coordenada[1], o.coordenada[1]); }
2. 补充重写hashCode方法
虽然TreeMap不依赖hashCode,但根据Java的约定,重写equals必须同时重写hashCode,否则如果这个类以后被用到HashMap、HashSet等基于哈希的集合中,会出现不可预期的问题。添加如下实现:
@Override public int hashCode() { return Objects.hash(coordenada[0], coordenada[1]); }
为什么之前的代码会出现问题?
当你调用map.putIfAbsent(c, new TreeMap<>())插入Coordenada(12,2)时,TreeMap通过错误的compareTo逻辑将它放到了某个位置;之后调用map.get(helper_co)时,helper_co虽然和插入的键equals返回true,但compareTo的结果不为0,TreeMap会认为这是两个不同的键,因此返回null。
修正compareTo后,TreeMap的排序和键判断逻辑会和equals保持一致,就能正常找到已插入的键了。
内容的提问来源于stack exchange,提问作者sckv

