正确重写hashCode的办法

正确重写hashCode的办法

[1]. hashCode重写成相同的值缺点

将所有对象的hashCode都返回一样的值是不科学的。比如a1和a3这两个根本不同的对象,就没有必要去比较equals,增加无谓的计算量所以应该对象本身的内容 (属性)来重写hashCode。

一旦两个对象内部不一样,就直接判定出hashCode不一样不用再调用equals进行比较

[2]. 正确书写hashCode的办法:

【原则】按照equals()比较两个对象是否一致条件用到的属性重写hashCode()

{1}. 常用的办法就是利用涉及到的的属性进行线性组合

{2}. 线性组合过程中涉及到的组合系数自定义即可。

注意,拼接之后的数值不能超过整形的表达范围。

{3}. 公式:属性1int形式+C1*属性2int形式C2*属性3int形式+…

【技巧】属性是引用类型的时候,如果已经重写过hashCode(),那么这个引用属性的int形式就是直接调用属性已有的hashCode值。

最典型的就是这个属性是字符串类型的,String类型已经重写了hashCode()方法,所以直接拿来使用即可。

### Java 中 Set 的 `remove` 方法失效的原因 在 Java 中,当调用 `Set` 接口实现类(如 `TreeSet` 或 `HashSet`)的 `remove` 方法时,如果该方法未能成功移除指定对象,则可能是由于以下几个原因: #### 1. **对象未正确重写 `equals()` 和 `hashCode()`** 对于基于哈希表的集合(如 `HashSet`),其依赖于对象的 `hashCode()` 和 `equals()` 方法来判断两个对象是否相同。如果自定义的对象没有正确重写这两个方法,可能导致即使逻辑上认为相同的对象也无法被识别为相等[^4]。 ```java class CustomObject { private int id; public CustomObject(int id) { this.id = id; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof CustomObject)) return false; CustomObject that = (CustomObject) o; return id == that.id; } @Override public int hashCode() { return Objects.hash(id); } } ``` 通过上述方式重写了 `equals()` 和 `hashCode()` 后,`HashSet` 才能正确比较并删除对象。 --- #### 2. **使用 `TreeSet` 时未提供合适的比较器** `TreeSet` 是基于红黑树的数据结构,默认按照自然顺序排列元素。如果自定义对象未实现 `Comparable` 接口或者提供了不一致的比较逻辑,可能会导致无法正常查找或删除元素。 ```java class CustomObject implements Comparable<CustomObject> { private int id; public CustomObject(int id) { this.id = id; } @Override public int compareTo(CustomObject other) { return Integer.compare(this.id, other.id); } } ``` 确保实现了 `compareTo` 方法,并且返回的结果与 `equals()` 方法保持一致性。 --- #### 3. **并发修改问题** 某些集合(如 `ArrayList.iterator` 实现中的 `remove` 方法)会维护一个内部计数器 `modCount` 来检测是否有其他线程正在修改集合。如果没有同步访问控制,可能引发 `ConcurrentModificationException` 或者使 `remove` 失效[^1]。 可以通过以下方式进行改进: - 使用线程安全的集合替代品,例如 `CopyOnWriteArraySet`。 - 对集合的操作加锁以防止并发冲突。 --- #### 4. **目标对象不存在于集合中** 有时开发者误以为某个对象存在于集合中而尝试调用 `remove` 方法。实际上,只有完全匹配的对象才能被移除。这通常发生在创建新实例而非引用已有实例的情况下。 ```java Set<String> set = new HashSet<>(); set.add("example"); // 错误做法:新建了一个不同的字符串对象 String toRemove = new String("example"); boolean removed = set.remove(toRemove); // 返回 false // 正确做法:直接传递字面量 removed = set.remove("example"); // 返回 true ``` 因此,在调用 `remove` 前应确认要移除的对象确实存在於集合中。 --- ### 总结解决方案 针对以上提到的各种情况,以下是具体的解决办法: 1. 如果是 `HashSet` 类型,需确保自定义对象已正确覆盖 `equals()` 和 `hashCode()` 方法。 2. 若采用的是 `TreeSet`,则需要保证对象实现了 `Comparable` 接口或是显式指定了比较器。 3. 防范多线程环境下的数据竞争条件,考虑引入同步机制或选用更健壮的数据结构。 4. 调试程序前先验证待删项的确切身份及其状态。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值