Set集合

Set集合

无序,不允许存放重复的元素;
实现类:

  1. HashSet:基于HashMap实现。用HashMap作为数据存储,无序,线程不安全。元素可以为 NULL。
  2. LinkedHashSet:基于LinkedHashMap实现。继承 HashSet,用LinkedHashMap作为数据存储,保证了元素迭代的顺序,即插入顺序。
  3. TreeSet:红黑树算法实现。擅长于范围查询。元素的类必须实现 Comparable 接口。所以不能放入 null。

HashSet

  1. 用HashMap作为数据存储,所有元素都存放在HashMap的key上面,定义一个虚拟的 Object 对象PRESENT 作为 HashMap 的 value 。
  2. HashMap最多只允许一个key为null,所以HashSet的元素可以为 NULL。
  3. HashMap无序,线程不安全,所以HashSet也是无序,线程不安全的。

源码分析

属性

    private transient HashMap<E,Object> map;
    private static final Object PRESENT = new Object();

定义一个 HashMap 作为数据存储,
定义一个虚拟的 Object 对象 PRESENT作为 HashMap 的 value 。

构造器

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

   
    public HashSet(Collection<? extends E> c) {
     
        map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
        addAll(c);
    }

  
    public HashSet(int initialCapacity, float loadFactor) {
     
        map = new HashMap<>(initialCapacity, loadFactor);
    }

 
    public HashSet(int initialCapacity) {
     
        map = new HashMap<>(initialCapacity);
    }
//此构造器是LinkedHashSet实例化调用
    HashSet(int initialCapacity, float loadFactor, boolean dummy) {
     
        map = new LinkedHashMap<>(initialCapacity, loadFactor);
    }

可以看到HashSet的构造器就是new了一个HashMap。

方法

 public Iterator<E> iterator() {
      return map.keySet().iterator(); }
 
    public int size() {
       return map.size();  }
    
    public boolean isEmpty() {
       return map.isEmpty();  }
    
    public boolean contains(Object o) {
     return map.containsKey(o);}
    
    public boolean add(E e) {
     return map.put(e, PRESENT)==null;}
    
    public boolean remove(Object o) {
      return map.remove(o)==PRESENT;}

可以看到HashSet的绝大部分方法都是通过调用HashMap 的方法来实现的,因此HashSet 和HashMap 两个集合在实现本质上是相同的。区别在于HashSet只存放一个key,而HashMap存放的是键值对。
想了解HashMap的小伙伴请点击链接HashMap源码分析

LinkedHashSet

基于LinkedHashMap实现。用LinkedHashMap作为数据存储,保证了元素迭代的顺序,即插入顺序。继承 HashSet,其内部只定义spliterator()方法。可以直接调用父类HashSet的方法。
LinkedHashSet继承HashSet

public class LinkedHashSet<E>
    extends HashSet<E>
    implements Set<E>, Cloneable, java.io.Serializable {
     

构造器

  public LinkedHashSet(int initialCapacity, float loadFactor) {
     
        super(initialCapacity, loadFactor, true);
    }

    public LinkedHashSet(int initialCapacity) {
     
        super(initialCapacity, .75f, true);
    }
    
    public LinkedHashSet() {
     
        super(16, .75f, true);
    }

   
    public LinkedHashSet(Collection<? extends E> c) {
     
        super(Math.max(2*c.size(), 11), .75f, true);
        addAll(c);
    }

 HashSet(int initialCapacity, float loadFactor, boolean dummy) {
     
        map = new LinkedHashMap<>(initialCapacity, loadFactor);
    }

可以看到LinkedHashSet的构造器都调用了父类HashSet的HashSet(int initialCapacity, float loadFactor, boolean dummy)构造器new了一个LinkedHashMap。因此LinkedHashSet 和LinkedHashMap 两个集合在实现本质上是相同的。但new LinkedHashMap时,并没有设置accessOrder,所以LinkedHashSet只能实现插入顺序,不能实现访问顺序。(这个不太确定,如结论有误,评论区期待大佬指正!!!)
想了解LinkedHashMap的小伙伴请点击链接LinkedHashMap源码分析

TreeSet

基于TreeMap实现,应用方法都一样;值都为new Object();

你可能感兴趣的:(java)