在java集合中,判断对象是否相等的规则是:
(1)判断两个对象的hashCode是否相等,如果不相等,则认为两个对象也不相等。如果相等转入(2)
(2):判断两个对象的equals运算是否相等,如果不相等则认为两个对象也不想等,如果相等认为两个对象相等。
============================================================
如何理解hashCode的作用:
============================================================
以java.lang.Object来理解,JVM每new一个Object,它都会将这个Object丢到一个Hash哈希表中去,这样的话,下次做Object的比较或者取这个对象的时候,它会根据对象的hashcode再从Hash表中取这个对象。这样做的目的是提高取对象的效率。具体过程是这样:
1.new Object(),JVM根据这个对象的Hashcode值,放入到对应的Hash表对应的Key上,如果不同的对象确产生了相同的hash值,也就是发生了Hash key相同导致冲突的情况,那么就在这个Hash key的地方产生一个链表,将所有产生相同hashcode的对象放到这个单链表上去,串在一起。
2.比较两个对象的时候,首先根据他们的hashcode去hash表中找他的对象,当两个对象的hashcode相同,那么就是说他们这两个对象放在Hash表中的同一个key上,那么他们一定在这个key上的链表上。那么此时就只能根据Object的equal方法来比较这个对象是否equal。当两个对象的hashcode不同的话,肯定他们不能equal.
============================================================
改写equals时总是要改写hashCode
============================================================
java.lnag.Object中对hashCode的约定:
1. 在一个应用程序执行期间,如果一个对象的equals方法做比较所用到的信息没有被修改的话,则对该对象调用hashCode方法多次,它必须始终如一地返回同一个整数。
2. 如果两个对象根据equals(Object o)方法是相等的,则调用这两个对象中任一对象的hashCode方法必须产生相同的整数结果。
3. 如果两个对象根据equals(Object o)方法是不相等的,则调用这两个对象中任一个对象的hashCode方法,不要求产生不同的整数结果。但如果能不同,则可能提高散列表的性能。
有一个概念要牢记,两个相等对象的equals方法一定为true, 但两个hashcode相等的对象不一定是相等的对象。
所以hashcode相等只能保证两个对象在一个HASH表里的同一条HASH链上,继而通过equals方法才能确定是不是同一对象,如果结果为true, 则认为是同一对象在插入,否则认为是不同对象继续插入。
重写hashCode 与equals 方法:
一般使用java中的Map对象进行存储的时候,其会自动调用hashCode方法来比较两个对象是否相等,所以如果对equals 进行重写一定要对hashCode方法进行重写,保证相同的对象返回相同的哈希值,不同的对象返回不同的哈希值。
如果只重写equals,不重写hashCode ,则hashCode就是继承自Object返回内存编码。这时可能出现equals 相等,而hanhCode不等,你的对象使用集合时,就会等不到正确结果。
实例如下:
package com.xiyou.hasCode;
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public void setAge(int age) {
this.age = age;
}
/*
* 重写hashCode (假如在HashSet中添加相同的数据(相同年龄与姓名)的时候,可以不允许其添加进去 )。
* 重写HashCode 时应该注意也要重写equals方法
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
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;
Person other = (Person) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
测试类:
/* hashcode ()方法,在object中定义如下:
* public native hashCode ()
* 是本地方法,其实现与本地机器有关,当然覆盖它
*/
public class HasCode {
public static void main(String[] args) {
HashSet< Person > set = new HashSet<>();
Person p = new Person("小白", 14);
Person p2 = new Person("小虎",13);
System.out.println("p hashCode="+p.hashCode());
System.out.println("p1 hashCode="+p2.hashCode());
System.out.println("p 的散列值"+p.hashCode()%16);
System.out.println("p1 的散列值"+p2.hashCode()%16);
set.add(p);
set.add(p2);
System.out.println(set.size());
set.add(new Person("小虎",15));
System.out.println(set.size());
}
}