equals hashCode
equals() hashCode()
equals()
equals()默认比较引用地址,重写equals()可实现判断对象内同是否相等,一般用于集合元素的比较,避免重复插入。
equals() 必须满足的条件
equals()方法要求我们必须满足以下条件:
- 自反性(Reflexive):对于非null的x来说,x.equals(x)必须返回true;
- 对称性(Symmetric):对于非null的x和y来说,如果x.equals(y)为true,则y.equals(x)也必须为true;
- 传递性(Transitive):对于非null的x、y和z来说,如果x.equals(y)为true,y.equals(z)也为true,那么x.equals(z)也必须为true;
- 一致性(Consistent):对于非null的x和y来说,只要x和y状态不变,则x.equals(y)总是一致地返回true或者false;
- 对null的比较:即x.equals(null)永远返回false。
hashCode()
哈希码:哈希码产生的依据:哈希码并不是完全唯一的,它是一种算法,让同一个类的对象按照自己不同的特征尽量的有不同的哈希码,但不表示不同的对象哈希码完全不同。也有相同的情况,看哈希码的算法实现。
hashCode()的常用实现
根据对象的值计算其物理存储位置,即hash值,两个equals相等的对象,其hashCode一定相等,但是即使值不相等,也可能得到相同的hash值,因为在同一hash值的位置形成了链表,可以看出,每次new出一个对象,直接计算出其hash值,然后寻找对应位置上,再使用equals方法比较,是否已存在值就可以知道对象是否重复了,这样比依次调用equals()与集合中的每个元素比较要节省很多时间。hash地址允许冲突,但是设计的越分散性能越好。
- Object类的hashCode():返回对象所在的内存地址经过处理后的结构,由于每个对象的内存地址都不一样,所以哈希码也不一样。
- String类的hashCode():根据String类包含的字符串的内容,根据一种特殊算法返回哈希码,只要字符串所在的堆空间相同,返回的哈希码也相同。
- Integer类,返回的哈希码就是Integer对象里所包含的那个整数的数值,例如Integer i1=new Integer(100),i1.hashCode的值就是100,由此可见,2个一样大小的Integer对象,返回的哈希码也一样。
equals()与hashCode()的结果比较
- equals相等,hashcode一定相等
- equals不等,hashcode不一定不等
- hashcode相等,equals不一定相等
- hashcode不等,equals一定不等
重写equls() hashCode()
建议使用ecplise自动生成。
二者必须同时重写:
假如只重写equals而不重写hashcode,那么Student类的hashcode方法就是Object默认的hashcode方法,由于默认的hashcode方法是根据对象的内存地址经哈希算法得来的,显然此时s1!=s2,故两者的hashcode不一定相等。
然而重写了equals,且s1.equals(s2)返回true,根据hashcode的规则,两个对象相等其哈希值一定相等,所以矛盾就产生了,因此重写equals一定要重写hashcode,而且从Student类重写后的hashcode方法中可以看出,重写后返回的新的哈希值与Student的两个属性有关。
Demo
JavaBean
public class EqualsDemoClass {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((value == null) ? 0 : value.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;
EqualsDemoClass other = (EqualsDemoClass) obj;
if (value == null) {
if (other.value != null)
return false;
} else if (!value.equals(other.value))
return false;
return true;
}
}
Main
public class App
{
public static void main( String[] args )
{
EqualsDemoClass a = new EqualsDemoClass();
a.setValue("1");
EqualsDemoClass b = new EqualsDemoClass();
b.setValue("1");
/**
* 未重写,返回值为fale,因为比较的是二者的引用地址
* 重写后,返回值为true,比较的是两个对象的值
*/
System.out.println(a.equals(b));
/**
* 未重写,返回值不同,因为是根据对象物理地址算出
* 重写后,返回值相同,是根据对象的值算出
*/
System.out.println(a.hashCode());
System.out.println(b.hashCode());
}
}