Set集合的继承结构图、HashSet底层、LinkedHashSet的理解

264 阅读2分钟

Set集合

  1. 无序,没有索引,添加和取出的顺序不一样
  2. 不允许重复元素,最多包含一个null
  3. 常用方法和Collection接口一样
  4. 不能通过索引方式来获取元素
  5. 循环遍历:增强for循环,迭代,不能使用普通for循环,没有get方法

1.迭代遍历:

Set set = new HashSet(); 
Iterator it = set.iterator(); 
while (it.hasNext()) {  
    String str = it.next(); System.out.println(str); 
}

2.for循环遍历:

for (String str : set) {  
    System.out.println(str); 
}

Set的继承结构图

set继承结构图.png

hashSet的理解

源码分析见: 详情debug调试hashSet底层

底层是hashmap,hashmap的结构是:数组+链表+红黑树的结构

public HashSet() {
    map = new HashMap<>();
}

HashSet的添加操作

package JavaTest;
import java.util.HashSet;
public class HashSetTest {
    public static void main(String[] args) {
        HashSet hashSet   = new HashSet();

        System.out.println(hashSet.add(new String("lzq")));
        // 添加失败,有线程池的原因
        System.out.println(hashSet.add(new String("lzq"))); 

        System.out.println(hashSet.add(new DogA("旺财"))); // 添加成功
        System.out.println(hashSet.add(new DogA("旺财"))); // 添加成功
        System.out.println(hashSet);
    }
}
class DogA{
    public String name ;

    public DogA(String name) {
        this.name = name;
    }
}

HashSet底层原理总结

  1. HashSet底层是HashMap
  2. 添加一个元素时,先得到hash值,会转成->索引值
  3. 找到出处数据table表,看这个索引位置是否已经存放元素
  4. 如果没有,直接加入
  5. 如果有,调用equals方法进行比较,如果相同就放弃添加,如果不相同则添加到最后
  6. 在Java8中,如果一条链表的元素个数达到TREEIFY_THRESHOLD(默认为8) , 并且 table大小>=MIN_TREEIFY_CAPACITY(默认为64),就会进行红黑树化

LinkedHashSet的理解

  1. LinkedHashSet是HashSet的子类

    public class LinkedHashSet<E>
     extends HashSet<E>
     implements Set<E>, Cloneable, java.io.Serializable {
    
  2. LinkedHashSet底层是一个LinkedHashMap,底层维护了一个table数组+双链表

  3. LinkedHashSet根据元素的hashcode值来决定元素的存储位置, 同时使用了链表维护元素的次序,是的元素看起来是插入顺序保存的

  4. LinkedHashSet不允许添加重复元素,可以保证元素的有序性

  5. 每一个节点有before和after属性,这样可以形成双向链表

  6. 在添加一个元素时,先求hash值,再求索引,确定该元素在table的位置,然后将添加的元素加入到双向链表(如果已经存在,不添加)

  7. 第一次添加时,将数组直接扩容为16,存放的结点类型为LinkedhashMap&Entry (多态数组)数组是HashMapNode[]存放的元素/数据是LinkedHashMapNode[] 存放的元素/数据是LinkedHashMapEntry类型

  8. 示意图

LinkedHashSet.png