去重原理简介:
HashSet是Java集合框架中的一种数据结构,用于存储不重复的元素。它基于哈希表(Hash Table)实现,并使用哈希函数将元素映射到哈希表中的位置。
HashSet的去重原理是利用哈希表的特性来判断元素是否已经存在。当我们向HashSet中添加一个元素时,它会首先计算该元素的哈希码(通过调用元素对象的hashCode()
方法),然后根据哈希码找到对应的哈希表中的位置。
如果该位置上没有其他元素,就直接将该元素插入到该位置,并标记为已占用。如果该位置上已经有其他元素存在,那么就需要比较新元素和已存在元素是否相等(通过调用元素对象的equals()
方法)。如果相等,说明元素已经存在于HashSet中,不做任何操作;如果不相等,就发生了哈希冲突,需要采取解决冲突的方法,例如使用链表或者树结构来处理冲突。
通过这种方式,HashSet可以保证其中的元素不重复,因为在添加元素时会进行哈希码的比较和相等性判断。当我们需要判断一个元素是否已经存在于HashSet中时,它会根据元素的哈希码快速定位到可能的位置,然后再进行相等性比较,从而实现高效的去重操作。
详细解析:
HashSet加入的对象需要重写hashCode方法和equals方法,因为对于自定义类需要提供判断怎样才算重复元素的方法。
HashSet的特点
1.元素不能重复且无序
2.允许有null值
3.线程不安全
4.底层的数据结构是HashMap
Hashset的实现原理
1.在HashSet中,元素被存放在HashMap的key中,value则是一个常量对象,所以HashSet能够保证元素的不重复。
2.当我们向HashSet中添加元素时,HashSet会调用该元素的HashCode()方法计算出该元素的哈希值,然后根据哈希值计算出该元素在数组中存放的位置,如果该位置没有元素,就直接将该元素存放在当前位置,如果该位置有元素,就会调用equals()方法来对俩个元素比较,如果比较值是true,HashSet会认为这俩个元素一样,就不会对其进行存储,如果比较值是false,HashSet会认为这俩个元素不一样,就会用开放寻址法在数组中查找可以存放该元素的空位置进行存储。
hashCode()与equals()的相关规定
1.如果两个对象相等,则hashcode一定也是相同的
2.两个对象相等,对两个equals方法返回true
3.两个对象有相同的hashcode值,它们也不一定是相等的
4.综上,equals方法被覆盖过,则hashCode方法也必须被覆盖
5.hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写hashCode(),则该class的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)。
代码解析
此时没有重写hashcode()和equals()方法
package Test;
public class User {
private String name;
public User(String name) {
this.name = name;
}
}
package Test;
import java.util.HashSet;
import java.util.Set;
public class Demo02 {
public static void main(String[] args) {
User u1 =new User("关羽");
User u2 =new User("关羽");
Set<User> ser =new HashSet<User>();
ser.add(u1);
ser.add(u2);
System.out.println(ser);
}
}
俩个user对象都是关羽,但是没有重写HashCode()和equals()方法,所以HashCode()值不一样,所以 HashSet认为添加进去的俩个user对象是不同的
我们重写了HashCode()和equals()方法之后再进行测试
package Test;
public class User {
private String name;
public User(String name) {
this.name = name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.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;
User other = (User) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public String toString() {
return "name=" + name;
}
package Test;
import java.util.HashSet;
import java.util.Set;
public class Demo02 {
public static void main(String[] args) {
User u1 =new User("关羽");
User u2 =new User("关羽");
Set<User> ser =new HashSet<User>();
ser.add(u1);
ser.add(u2);
System.out.println(ser);
}
}
可以看出当我们重写了HashCode()和equals()方法之后HashSet会认为我们添加的俩个user对象是同一个user对象;