Java学习-集合框架-Set实现类-HashSet
1.基于HashCode计算元素存放位置
2.当存入元素的哈希值相同时,调用 equals 进行确认,结果为 true则拒绝后者进入
案例1:
HashSet<String> hashSet = new HashSet<>();
haseSet.add("刘德华");
haseSet.add("梁朝伟");
haseSet.add("周润发");
haseSet.add("周星驰");
haseSet.add("梁朝伟");//重复元素
//不重复
sout(hashSet.szie());//→ 4
//无序
sout(hashSet.toString());//→ [周星驰,梁朝伟,周润发,刘德华]
//删除
hashSet.remove("周星驰");
sout(hashSet.szie());//→ 3
//遍历
for(String string : hashSet){sout(string);}
//→ 梁朝伟 \n 周润发 \n 刘德华
Iterator<String> it = hashSet.iterator();
while(it.hasNext()){sout(it.next());}
//→ 梁朝伟 \n 周润发 \n 刘德华
//判断
sout(set.contains("刘德华"));//→ true
sout(set.isEmpty());//→ false
案例2:
public class Person{
private String name;
private int age;
@override
public String toString(){
return "Person ["+name+","+age+"]";
}
}
public class Demo{
public static void main(String[] args){
HashSet<Person> persons = new HashSet<>();
Person p1 = new Person("林志玲",20);
Person p2 = new Person("范冰冰",22);
Person p3 = new Person("林青霞",18);
persons.add(p1);
persons.add(p2);
persons.add(p3);
persons.add(p2);//重复元素
//不重复
sout(persons.size());//→ 3
//无序
sout(persons.toString());//→ [Person[林青霞,18],Person[范冰冰,22],Person[林志玲,20]]
}
}
HashSet 存储方式
HashSet<Person> persons = new HashSet<>();
Person p1 = new Person("林志玲",20);
Person p2 = new Person("范冰冰",22);
Person p3 = new Person("林青霞",18);
persons.add(p1);
persons.add(p2);
persons.add(p3);
persons.add(new Person("林志玲",20));//加入姓名和年龄相同的对象
sout(persons.size());//4
sout(persons.toString());//→ [Person[林青霞,18],Person[范冰冰,22],Person[林志玲,20],Person[林志玲,20]]
分析原因:存储过程:
1.根据 hashcode就算保存的位置
2.如果位置为空,直接保存
3.不为空,执行 equals 方法,如果结果为 true,认为是重复元素拒绝加入,否则形成链表
新实例化的匿名对象虽然姓名和年龄都与 p1 相同,但是两个对象,equals 返回为 false
想要实现相同姓名和年龄的对象不重复添加的功能,需要重写 equals 方法
public class Person{
...
@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;
}
@overrride
public boolean equals(Object obj){
if(this == obj)return true;
if(obj == null)return false;
if(obj instanceof Person){
Person p = (Person)obj;
if(this.name.euqals(p.getName()) && this.gae == p.getAge())return true;
}
return false;
}
}
HashSet<Person> persons = new HashSet<>();
Person p1 = new Person("林志玲",20);
persons.add(p1);
persons.add(new Person("林志玲",20));
sout(persons.size())//→ 1
sout(persons.toString());//→ [Person[林志玲,20]]
//遍历
for(Person person : persons){sout(person.toString());}
//→ [Person[林志玲,20]]
//删除
persons.remove(new Person("林志玲",20));
sout(persons.size());//→ 0
//判断
sout(persons.isEmpty());//→ true
补充:为什么重写 hashCode 函数要 + prime ?
1.31是质数,减少散列冲突
2.31提高执行效率:31*i = (i<<5)-i