HashSet的去重
HashSet
HashSet存储的数据结构是哈希表,也就是数组和链表的组合物。
此类实现Set接口,由哈希表(实际上是一个HashMap实例)支持。它不保证set的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用null元素。Hash:哈希——实际含义散列,就是一种算法,把任意长度的输入通过散列算法变换成固定长度的输出,该输出就是散列值。
哈希表:数组加链表,既有数组的优点也有链表的优点。
存储特点:
相对无序存储,不可以存储相同元素(排重),通过哈希表实现的集合
HashSet去重
HashSet底层依赖的是哈希表,在元素存放时候,会先根据元素的hashcode值来判定,如果没有相等的hashcode值则放入数组中,(hashCode()是Object中的方法,每个对象的hashCode值是唯一的,所以可以理解成hashCode值表示这个对象在内存中的位置
字符串String的hashCode(),是根据内容计算的。)若hashcode相等,则会用equls方法来比较,equals()方法是Object类中的方法,表示比较两个对象是否相等,若不重写相当于比较对象的地址,因此当用HsshSet来去重字符串和基本数据类型的时候,hashcode比较的是内容。
》》当我们在添加相同的学生类对象的时候,我们发现相同的属性信息的学生也可以添加进去,便会产生疑惑,为什么HashSet不是又去冲的效果吗?怎么还会有重复的元素呢?
张三实行是相同的运行结果还是会有两个相同张三,并没有去除重复
这是因为当我们传入的对象是对象类型的时候,由于每个对象的hashcode值都不一样,而我们传入对象的属性却又可不能一样的,这样hashset依然不能将属性相同的对象看作同一对象,那么这时候我们可以重写对象类中的hashcode方法和equls方法,用对象的属性值相同与否来确定是否重复代码如下:
public class Student {
private String name;
public Student(String name) {
super();
this.name = name;
}
public Student() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student [name=" + name + "]";
}
@Override
//重写equals
public boolean equals(Object obj) {
//先判断传入的参数对象是否是Student对象,若不是直接返回false
if(obj instanceof Student) {
//若是,强转成Student对象,并比较属性的值
Student s = (Student) obj;
if(this.name.equals(s.name)) {
//若属性的值相同,则返回true
return true;
}
}
return false;
}
@Override
public int hashCode(){
/*hashCode方法返回值是int类型,所以重写时需要找到int类型的数据返回,还要保证此方法的返回值与对象的所有属性都相关,所以返回姓名属性的字符串的长度*/
return this.name.hashCode();
}
}
这里我们在Student类中重写了hashcode和equls方法,将对象的属性值来作为去重的判定条件,这样在添加属性相同的对象时候,属性相同的对象就不会被添加进去。
!!!同样HashSet的remove()方法底层也是哈希表来实现的 当我们删除一个元素时候在remove中添加一个对象张三,虽然属性值相同,但是两个对象的hashcode和equls没有重写时候对象地址值是不同的,因此传入的对象在没有重写两个方法时候,也是不能删除的哈上图看一下:
运行的结果还是…
重写hashcode和equls方法在添加和删除就都ok了。(IDEA中都会有自带的重写方法快捷键 :Alt+ins)