- 1.HashSet简单说明
- 2.案例说明
- 3.hashSet底层源码
(1)说明
- HashSet实现了Set接口
- HashSet实际上是HashMap,看下图源码
- 可以存放null值,但是只能有一个
- HashSet不保证元素是有序的,取决于Hash后,再确定索引的结果(不保证存放元素的顺序和取出的顺序一致)。
- 不能有重复元素/对象,前面Seth中已说明。
package Collection.hashSet;
import java.util.HashSet;
public class hashSetTest2 {
public static void main(String[] args) {
HashSet hashSet = new HashSet();
//1. 在执行 add 方法后,会返回一个 boolean 值
// 2. 如果添加成功,返回 true, 否则返回 false
// 3. 可以通过 remove 指定删除哪个对象
hashSet.add("lucy");//T
hashSet.add("lucy");//F
//创建两个Dog对象,名字和age均相同,可以添加成功
HashSet hashSet1=new HashSet();
hashSet1.add(new Dog("嘿嘿",3));//T
hashSet1.add(new Dog("嘿嘿",3));//T
for (Object o : hashSet1) {
System.out.println(o);
}
//面试题:利用String创建两个对象,内容相同,
//添加不了的原因:
//因为String类中重写了hashcode和equals方法
//而hashset在添加时,会利用hashcode和equals方法比较当前添加对象或元素是否相等
//当将Dog类中重写hashcode和equals方法后,发现,上面添加时new Dog("嘿嘿",3)
//也只能添加第一个。
HashSet hashSet2=new HashSet();
hashSet2.add(new String("小明"));//可以
hashSet2.add(new String("小明"));//添加不了
for (Object o : hashSet2) {
System.out.println(o);
}
}
}
class Dog{
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Dog dog = (Dog) o;
if (age != dog.age) return false;
return name != null ? name.equals(dog.name) : dog.name == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
}
3.hashSet底层源码
HashSet底层是HashMap,HashMap底层是(数组+链表+红黑树)
(1)HashSet添加元素的方式
- 先获取元素的哈希值(hashcode方法以及一个右移操作">>>"),源码计算公式 return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
- 对哈希值进行运算,得出一个索引值即为要存放哈希表中的位置号
- 如果该位置上没有其他元素,则直接存放;如果该位置上已经有元素,则需要进行equals判断,如果相等,则不再添加;如果不相等,则以链表的方式添加。
如下图解:
(2)HashSet底层解析
- HashSet底层是HashMap
- 添加一个元素时,先得到hash值-会转成索引值
- 找到存储数据表table,看这个索引位置是否已经存放有元素
- 如果没有,直接加入
- 如果有,调用equals比较,如果相同,就放弃添加;否则就添加到最后
- 在java8中,如果一条链表的元素个数到达TREEIFY_THRESHOLD(默认是8),并且table的大小>=MIN_TREEIFY_CAPACITY(默认64),就会进行树化(红黑树)。
涉及源码有些复杂,简单介绍:
package Collection.hashSet;
import java.util.HashSet;
public class hashSetTest {
public static void main(String[] args) {
HashSet set = new HashSet();
set.add("java");
set.add("php");
set.add("java");
System.out.println("set="+set);
}
}



