HashSet里面的对象是无序而且唯一的。
如何理解,看下面这段代码:
import java.util.*;
class Student
{
private String name;
private int age;
public Student(String name,int age)
{
this.name = name;
this.age = age;
}
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;
}
}
public class Demo1 {
public static void main(String[] args) {
HashSet hs = new HashSet();
hs.add(new Student("lisi",23)); // 1
hs.add(new Student("Zhaosi",20));
hs.add(new Student("wangwu",24));
hs.add(new Student("zhaosi",20));
Iterator ite = hs.iterator();
while(ite.hasNext())
{
Student stu = (Student)ite.next();
sop(stu);
}
sop(hs.contains(new Student("lisi",23))); // 2
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
许多人看见上面这段代码会认为输出HashSet里面的4个对象以及一个true.这是错误的,1处的new Student("lisi",23)和2处的new Student("lisi",23)是两个不同的对象,虽然它们具有相同的内容。即使注释掉2处的代码,把添加4个对象的语句改成如下:
hs.add(new Student("lisi",23));
hs.add(new Student("lisi",23));
hs.add(new Student("wangwu",24));
hs.add(new Student("zhaosi",20));
仍然会生成4个对象而不是3个对象,编译仍然能通过,运行也毫无问题。
上面的代码正确的运行结果如下:
hashSet.Student@1fb8ee3
hashSet.Student@c17164
hashSet.Student@61de33
hashSet.Student@14318bb
false
为什么会出现这种情况?如何让HashSet认为内容相同的两个对象是一个对象?例如把语句:
hs.add(new Student("lisi",23));
hs.add(new Student("lisi",23));
看成一个对象,而非两个不同的对象。
这就要说到对象在HashSet里面的表示了,一般来说打印出来的结果的形式是这样的:类名@哈希码,如上面的运行结果hashSet.Student@1fb8ee3就是这样的,哈希码的不同就以为这是不同的对象,所以即使添加两个内容相同的对象,但它们具有不同的哈希码,也就是说它们是不同的对象。如果要让HashSet认为内容相同的两个对象是同一个对象,那么就要改写产生生成一个对象是产生哈希码的hashCode()这个函数和equals(Object obj)这个函数,同是为了让大家更容易理解生成对象时产生哈希码和判断HashSet里面是否以及存在该对象的过程以及为何会输出上面的运行结果的形式表达一个对象,我会同时改写toString()这个函数,实际上就是在Student类里面覆盖hashCode(),equals(Object obj)和toString()这三个函数。在Student类里面添加下面三个函数(实际Student类里面本身隐含着3个函数,只不过要覆盖);
public int hashCode()
{
return name.hashCode()+age;
}
public boolean equals(Object obj)
{
if(!(obj instanceof Student))
throw new RuntimeException("不是学生");
Student stu = (Student)obj;
return this.name.equals(stu.name) && this.age==stu.age;
}
public String toString()
{
return this.name+","+this.age;
}
再次运行,结果如下:
wangwu,24
zhaosi,20
lisi,23
true
hashSet里面有三个对象,并且是无序的,而且我们能看出三个对象在里面的顺序,开始运行时的那次结果就看不出各对象的顺序,并且判断new Student("lisi",23)已经存在,输入true