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不是又去冲的效果吗?怎么还会有重复的元素呢?

java hashset去重后自动排序了 hashset去重原理_ide

张三实行是相同的运行结果还是会有两个相同张三,并没有去除重复

java hashset去重后自动排序了 hashset去重原理_数组_02

这是因为当我们传入的对象是对象类型的时候,由于每个对象的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没有重写时候对象地址值是不同的,因此传入的对象在没有重写两个方法时候,也是不能删除的哈上图看一下:

java hashset去重后自动排序了 hashset去重原理_java_03


运行的结果还是…

java hashset去重后自动排序了 hashset去重原理_字符串_04


重写hashcode和equls方法在添加和删除就都ok了。(IDEA中都会有自带的重写方法快捷键 :Alt+ins)