一、hashCode方法与HashSet类
- 如果想查找一个集合中是否包含有某个对象,大概的程序代码怎样写呢?
- 通常是逐一取出每个元素与要查找的对象进行比较,当发现某个元素与要查找的对象进行equals方法比较的结果相等时
- 则停止继续查找并返回肯定的信息,否则,返回否定的信息
- 如果一个集合中有很多个元素,譬如有一万个元素,并且没有包含要查找的对象时,
- 则意味着你的程序要从该集合中取出一万个元素进行逐一比较才能得到结论
- 有人发明了一种哈希算法来提高从集合中查找元素的效率,这种方式将集合分成若干个存储区域,
- 每个对象可以计算出一个哈希码,可以将哈希码分组,每组分别对应某个存储区域,
- 根据一个对象的哈希码就可以确定该对象应该存储在哪个区域
- HashSet就是采用哈希算法存取对象的集合,
- 它内部采用对某个数字n进行取余的方式对哈希码进行分组和划分对象的存储区域
- Object类中定义了一个hashCode方法来返回每个java对象的哈希码,
- 当从HashSet集合中查找某个对象时
- java系统首先调用对象的hashCode方法获得该对象的哈希码
- 然后根据哈希码找到响应的存储区域
- 最后取出该存储区域内的每个元素与该对象进行equals方法比较,
- 这样不用遍历集合中的所有元素就可以得到结论
- 可见,HashSet集合具有很好的对象检索性能
- 但是,HashSet集合存储对象的效率相对要低些,
- 因为向HashSet集合中添加一个对象时,要先计算出对象的哈希码和根据这个哈希码确定对象在集合中的存放位置
- 为了保证一个类的实例对象能在HashSet正常存储,要求这个类的两个实例对象用equals方法比较的结果相等时
- 他们的哈希码也必须相等,
- 也就是说,如果obj1.equals(obj2)的结果为true,那么以下表达式的结果也要为true:
- obj1.hashCode() == obj2.hashCode()
- 如果一个类的hashCode方法没有遵循上述要求,
- 那么,当这个类的两个实例对象用equals方法比较了,也就可能被存储进HashSet集合中了,
- Object类中的hashCode方法不能满足对象被存入到HashSet中的要求,
- 因为他的返回值通过对象的内存地址推算出来的
- 同一个对象在程序运行期间的任何时候返回的哈希值都是始终不变的
- 所以,只要是两个不同的实例对象,即使他们的equals方法比较结果相等
- 他们默认的hashCode方法的返回值是不同的
- 通常来说,一个类的两个实例对象用equals方法比较的结果相等时,他们的哈希码必须相等,但反之则不成立
- 即:equals方法比较结果不相等的对象可以有相同的哈希码
- 或者说哈希码相同的两个对象的equals方法比较的结果可以不等
- 例如:字符串"BB"和"Aa"的equals方法比较结果肯定不相等,但他们的hashCode值却相等
- 当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了
- 否则,对象修改后的哈希值与最初存储进HashSet集合中时的哈希值就不同了
- 在这种情况下,即使在contains方法使用该对象的当前引用作为参数去HashSet集合中检索对象,也将返回找不到对象的结果
- 这也会导致无法从HashSet集合中单独删除当前对象,从而造成内存泄漏
二、示例
import java.util.*; public class HashCodeTest { public static void main(String[] args) { Collection col = new HashSet<Student>(); Student stu1 = new Student("zhangsan",20); Student stu2 = new Student("lisi",18); Student stu3 = new Student("wangwu",25); Student stu4 = new Student("zhangsan",20); col.add(stu1); col.add(stu2); col.add(stu3); col.add(stu4); col.add(stu1); /** * 改变参与hashCode运算的属性的值后,hashCode就变了 */ stu1.age = 15; System.out.println(col.contains(stu1));//false col.remove(stu1);//删不了stu1,造成了内存泄漏 System.out.println(col.size());//3 Iterator<Student> it = col.iterator(); while(it.hasNext()) { Student stu = it.next(); System.out.println(stu); } } } class Student { String name; int age; Student(String name,int age) { this.name = name; this.age = age; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Student other = (Student) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } public String toString() { return name+":"+age; } }
相关推荐
例如,在内存中有 8 个位置,分别是 0 1 2 3 4 5 6 7,我们可以通过 hashCode 将对象存放在这些位置之一。 hashCode 的实现 在 Java 中,hashCode 是 Object 类中的一个方法,默认情况下,该方法会将对象的内部...
#### 5. 示例代码解析 以下是一段示例代码,展示了如何使用`hashCode`方法和`equals`方法,并且解释了它们之间的关系: ```java public class Test { public static void main(String[] args) { HashSet<Demo1> ...
5. **非空性**:对于任何非null的引用值x,x.equals(null)应该返回false。 接下来是 `hashCode()` 方法,它用于返回对象的一个整数值,这个值可以作为对象在哈希表中的索引。当两个对象根据 `equals()` 方法判断...
5. 使用场景:ArrayList适合需要按顺序访问元素的情况,HashSet适合需要快速查找、插入和删除且不关心顺序的场景。 在实际开发中,选择ArrayList还是HashSet应根据具体需求来决定。理解这两个数据结构的特点以及...
5. 非 null 性:对于任何非空引用 x,x.equals(null) 应该返回 `false`。 在重写 `equals()` 时,通常使用 `Objects.equals()` 或者逐个比较各个属性,以确保满足上述原则。 `hashCode()` 方法: `hashCode()` 的...
同时,Java还提供了一些工具类和方法来帮助开发者实现hashCode方法,例如,Guava库中的Hashing类,它提供了多种hashCode算法,例如,MD5、SHA-1等。 Java中的hashCode方法是非常重要的,它直接影响着对象的比较和...
5. 非 `null` 参数:`x.equals(null)` 应该返回 `false`。 `hashCode()` 方法与 `equals()` 密切相关,因为它们共同决定了对象在哈希表中的行为。当两个对象通过 `equals()` 认为是相等的,它们的 `hashCode()` 值...
3. 使用更复杂的 Hash Code 算法:可以使用更复杂的 Hash Code 算法,如 SHA-1、MD5 等,这些算法可以生成更唯一的 Hash Code。 Hash Code 重复的可能性是 Java 开发中一个常见的问题。了解 Hash Code 的计算算法和...
5. **取模优化**:为了提高计算效率,避免循环取模操作,可以直接在累加过程中进行取模操作,避免超出JavaScript的安全整数范围。文件中的代码示例展示了如何在累加字符的ASCII值时即时进行取模操作,以保证最终的...
5. 除留余数法:取键除以不大于表长的某个数的余数作为哈希地址。 6. 随机数法:使用随机函数得到哈希地址。 在Java中,所有对象都有hashCode()方法,这个方法返回对象的一个整数值,作为其散列码。这个散列码用于...
Java中的`hashCode()`方法是基于对象的内部状态计算出的一个整数值,它在处理集合特别是HashSet、HashMap等基于哈希表的数据结构时起着至关重要的作用。哈希码(Hash Code)被用来快速定位对象在哈希表中的位置,...
5. **使用`Objects.hash()`**:Java 7引入了一个便捷的方法`Objects.hash()`,它可以简化`hashCode()`的实现,将多个字段的值组合成一个哈希码。 举个例子,如果我们有一个名为`Person`的类,包含`firstName`和`...
5. **测试示例**: - 示例代码中创建了一个名为 `A` 的类,重写了 `equals()` 和 `hashCode()` 方法。在 `main` 方法中,创建了一个 `HashMap` 并插入一个 `A` 类的实例。每次插入时,`hashCode()` 和 `equals()` ...
5、**为什么要重写hashCode()方法?** 当对象被放入哈希表时,`hashCode()`用于计算存储位置。如果两个对象`equals()`相等,它们的`hashCode()`也必须相等,以避免哈希冲突导致的性能下降。如果不重写`hashCode()`...
5. **与null的比较**:对于任何非null的引用值x,x.equals(null)应返回false。 接下来,我们来看`hashCode()`方法。`hashCode()`返回对象的一个整数值,用于哈希表中定位对象。两个相等的对象(根据`equals()`定义...
"java中的哈希算法和hashcode深入讲解" 哈希算法是计算机领域中非常重要的一种技术,它具有非常广泛的应用,例如快速查找和...5. 依次类推,直到计算完成。 最终,我们可以得到String类的hashCode值,也就是哈希值。
5. **如果x.equals(y)返回`false`,那么x和y的`hashCode()`值应该不同。** 这是因为不同的对象应该有不同的哈希码,这样它们才能被哈希表正确地区分。 违反这个契约可能会导致意想不到的行为,特别是在使用哈希表时...
5. 非空性:对于非null的x,存在x.equals(null)返回false。 例如,在String类中重写的equals方法如下所示: public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject ...
5. 在弹出的菜单中,选择“Equals HashCode”,然后点击或者直接按下对应的数字键(通常为`1`)。 IDEA会自动生成如下代码: ```java @Override public boolean equals(Object o) { if (this == o) return true; ...
其次,31*N可以被编译器优化为左移5位后减1,有较高的性能。最后,使用31作为系数可以使得hash code值的分布更加均匀,从而减少了哈希冲突的可能性。 在String类中,hashcode方法的实现使用了31作为系数,具体实现...