1、概述
1.1 HashSet不是线程安全的;
1.2 基于HashMap实现的;
1.3 *********JDK给出重写hashCode()的规则:***********
1.1.1 当2个对象的equals返回true,它们的hashCode()应该相等;
1.1.2 对象中用作equals比较的属性,都应该用来计算hashCode()值;
2、HashSet源码
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable{
//底层适应HashMap保存HashSet的所有元素
private transient HashMap<E,Object> map;
//使用一个虚拟的Object作为HashMap的value
private static final Object PRESENT = new Object(); /**
* 初始化HashSet时,默认使用HashMap的初始容量16、加载因子0.75
* default initial capacity (16) and load factor (0.75).
*/
public HashSet() {
map = new HashMap<>();
} public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
} public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}
//add时,底层实际将元素作为key放入HashMap中
public boolean add(E e) {
return map.put(e, PRESENT)==null;
} public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
}
3、重写equals(),hashCode()案例
package com.exiuge.mytest.hashset; public class Person { private int age; private String name; public Person(){ } public Person(int age,String name){
this.age=age;
this.name=name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Override
public int hashCode() {
return this.name.hashCode();
} @Override
public boolean equals(Object obj) {
if (obj instanceof Person){
Person p=(Person) obj;
if (p.getName().equals(this.name)){
return true;
}
}
return false;
}
}
package com.exiuge.mytest.hashset; import java.util.HashSet;
import java.util.Set; public class Test { public static void main(String[] args){
Person p1=new Person(12,"a");
Person p2=new Person(12,"a");
Set set=new HashSet();
boolean a=set.add(p1);
boolean b=set.add(p2);
System.out.println("p1 hashCode:"+p1.hashCode());
System.out.println("p2 hashCode:"+p2.hashCode());
System.out.println("equals:"+p1.equals(p2));
System.out.println(a+"====="+b);
}
}
执行结果: