深刻源码探讨HashSet

咱们在工做中时常会用到HashSet,面试也有时候容易被问到,下面我们就来聊聊HashSet
java

使用案例

public class Test {   public static void main(String[] args) {       HashSet<String> hashSet = new HashSet<>();       hashSet.add("Java");       hashSet.add("R");       hashSet.add("C");       hashSet.add("C#");       hashSet.add("C#");       hashSet.add("Java");       hashSet.add(null);       System.out.println("hashSet的长度:" + hashSet.size());       //第一种遍历方式       System.out.println("第一种方式遍历");       Iterator<String> iterator = hashSet.iterator();       while (iterator.hasNext()) {           System.out.print(iterator.next());           System.out.print(" ");       }       System.out.println("");       System.out.println("第二种方式遍历");       for (String string : hashSet) {           System.out.print(string);           System.out.print(" ");       }   }}

输出面试

hashSet的长度:5第一种方式遍历C# null Java R C第二种方式遍历C# null Java R C

从上面的例子能够得知几个结果:app

1,不能放入重复的。ide

2,不是按照放入的顺序存放的。spa

3,null也能够存放。3d

关键源码

HashSet的类图code

5e55ee5f29439b2aff7bbc008e4dfac0.png

咱们来看看HashSet究竟是怎么玩的orm

515d2095eac382c2f110a43c3a39cdd0.png

JDK1.2开始有的HashSet,实现了解耦Set,CloneableSerializable对象

  1. Set是个接口,定义了不少方法。blog

  2. Cloneable能够对象克隆。

  3. Serializable能够序列化与反序列。

  4. 继承了抽象类AbstractSet

AbstractSet也是Set接口的实现类,主要有如下几个方法:

1e5b94212a7d4d3fe9dc48902ec10b9f.png

AbstractSet实现了三个方法equalshashCoderemoveAll。而后全部继承AbstractSet的子类都不用本身去实现此三个方法。

Set定义了以下方法:

66d81ab3ca45a2f7c6ebeb317244f4f6.png

HashSet中关键的变量和方法:

//定义了一个HashMap类型的变量private transient HashMap<E,Object> map;// Dummy value to associate with an Object in the backing Map//与备份Map中的对象关联的虚拟值private static final Object PRESENT = new Object();public HashSet() {   map = new HashMap<>();}//设置HashSet的容量其实就是设置HashMap的容量public HashSet(int initialCapacity) {   map = new HashMap<>(initialCapacity);}//求HashSet的大小就是求HashMappublic int size() {  return map.size();}//往HashSet存放数据其实就是往HashMap存放数据//数据做为key,而后value就是固定Object对象PRESENTpublic boolean add(E e) {  return map.put(e, PRESENT)==null;}public Iterator<E> iterator() {  return map.keySet().iterator();}public int size() {  return map.size();}....//序列化与反序列化private void writeObject(java.io.ObjectOutputStream s){   //...}private void readObject(java.io.ObjectInputStream s){   //...}

能够看出,HashSet的操做都是基于HashMap的操做。

总结

HashSet的全部操做都是基于HashMap进行操做,用存放进HashSet的数据做为HashMap的key在使用一个固定Object对象做为HashMap的value。