HashSet<MySimpleObject>的contains方法行为异常问题求助
HashSet.contains() 异常排查:Hadoop Mapper 中自定义类问题
嘿,我在Hadoop的Mapper组件里遇到个棘手的问题,想请大伙帮忙看看:我用HashSet<MySimpleObject>存储一个仅含两个整数属性的自定义类实例,而且严格按照规范重写了hashCode()方法(equals()方法没贴全,先把现有代码放出来),但contains()方法的表现完全不对,没法正确识别已经存在的对象。
我的自定义类代码:
public class MySimpleObject { private int i1, i2; public set(int i1, int i2) { // 这里注意:Java方法必须声明返回类型,应该是public void set吧? this.i1 = i1; this.i2 = i2; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + i1; result = prime * result + i2; return result; } @Override public boolean equals(Object obj) { // 这里的实现没写完,我是按照规范写的,但不确定是不是哪里错了 // ... 我的代码内容 } }
我梳理的几个排查方向,也想请大家帮忙验证:
equals()方法是否完整正确:
HashSet判断对象存在是先靠hashCode定位哈希桶,再用equals确认匹配。如果equals没写对,哪怕hashCode正确也白搭。正确的equals实现应该包含这几步:- 先判断是否为同一对象引用:
if (this == obj) return true; - 判断obj是否为null或类型不匹配:
if (obj == null || getClass() != obj.getClass()) return false; - 强转后比较核心属性:
MySimpleObject other = (MySimpleObject) obj; return i1 == other.i1 && i2 == other.i2;
我是不是在这部分漏了关键逻辑?
- 先判断是否为同一对象引用:
对象存入HashSet后是否被修改:
会不会在Mapper逻辑里,把实例存入HashSet之后,又调用set()方法修改了i1或i2的值?如果是这样,对象的hashCode会发生变化,它在HashSet里的哈希桶位置就不对了,这时候调用contains肯定找不到——哪怕再改回原来的值也没用,因为哈希桶的位置已经错乱了。Hadoop序列化的潜在影响:
这个类会不会涉及Hadoop的Writable序列化(比如在Mapper不同阶段传递对象)?如果序列化/反序列化时没正确读写i1和i2,可能导致反序列化后的对象看起来属性一致,但实际hashCode或equals判断出错。
有没有大佬遇到过类似的问题,或者能帮我指出哪里可能踩坑了?
内容的提问来源于stack exchange,提问作者J. Doe
相关产品推荐
相关产品推荐

