写在前面,怎么判断是否相等,有地绕啊。。。原文地址:http://www.iteye.com/topic/257191
(1)equals()相等的两个对象,hashcode()一定相等;
(2)equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。换句话说,equals()方法不相等的两个对象,hashcode()有可能相等。(我的理解是由于哈希码在生成的时候产生冲突造成的)。
反过来:(1)hashcode()不等,一定能推出equals()也不等;然后直接写入就行了
(2)hashcode()相等,equals()可能相等,也可能不等。
解释下第3点的使用范围,我的理解是在object、String等类中都能使用。在object类中,hashcode()方法是本地方法,返回的是对象的地址值,而object类中的equals()方法比较的也是两个对象的地址值,如果equals()相等,说明两个对象地址值也相等,当然hashcode()也就相等了;在String类中,equals()返回的是两个对象内容的比较,当两个对象内容相等时,
Hashcode()方法根据String类的重写(第2点里面已经分析了)代码的分析,也可知道hashcode()返回结果也会相等。以此类推,可以知道Integer、Double等封装类中经过重写的equals()和hashcode()方法也同样适合于这个原则。当然没有经过重写的类,在继承了object类的equals()和hashcode()方法后,也会遵守这个原则。
注意1:首先集合HashSet和Equals方法都是判断两个对象的地址,因此在使用过程中,需要重新对HashSet和Equals进行重写。容纳的对象,必须根据自己的唯一标识,重写HashSet和equals方法
注意2:对象一旦放入到HashSet容器中,那么对象的属性值则不能修改,如果进行修改了,则没法进行remove操作。主要原因是HashSet存放元素的时候,元素的位置是和对象hashCode算法得到的值相关的。那么去查找元素时,也要根据这个算法的值,然后找到相关位置,移除元素,如果没有元素存在,那么久返回false,但是不会报错。如果该算法相关的属性值在放入容器中被修改,意味着HashCode算法存的值,和原来的不一样了,找对象的位置就发生了变化,找不到之前的对象,导致元素不能移除,久而久之导致内存泄露。
package link_list;
public class Student {
private String no;
private String name;
private int age;
public Student(){
}
public Student(String no, String name, int age) {
super();
this.no = no;
this.name = name;
this.age = age;
}
public String getNo() {
return no;
}
public void setNo(String no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return no+"_"+name;
}
@Override //重写的方法是为了实现,只要no这个变量相同,就是证明同一个对象,自动忽略,不再加入HashSet
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((no == null) ? 0 : no.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 (no == null) {
if (other.no != null)
return false;
} else if (!no.equals(other.no))
return false;
return true;
}
}
package link_list;
import java.util.HashSet;
public class HashSetDemo1 {
<span style="white-space:pre"> </span>public static void main(String[] args) {
<span style="white-space:pre"> </span>// TODO Auto-generated method stub
Student st1=new Student("001","zhangsan",22);
Student st2=new Student("002","lisi",24);
Student st3=new Student("003","wangwu",22);
HashSet<Student>students=new HashSet<Student>();
students.add(st1);
students.add(st2);
students.add(st3);
System.out.println(students.size());
System.out.println(students);
Student st4=new Student("003","wangyu",22);
System.out.println(st3.equals(st4));//这个地方为ture,因为重写了方法,只比较内容
students.add(st4);
st1.setNo("008");
student.remove(st1); //注意2:无法删除,size还是4个
System.out.println(students.size()); //这个地方,输出为3,但是如果在上面的student类中没有重写HashSet 方法,这个地方得出就是4
<span style="white-space:pre"> </span>}
}