JDK1.8集合框架之Set

总述

Set利用Map实现,不允许重复元素(Map中的Key值唯一,可为null)。

  • TreeSet,利用TreeMap实现。支持按插入顺序访问,但是添加、删除、包含等操作相对低效(log(n)时间)。
  • HashSet,底层是HashMap。利用哈希算法,理想情况,可以提供常数时间的添加、删除、包含等操作,但是不能保证有序。
  • LinkedHashSet,用LinkedHashMap实现。内部构建了一个记录插入顺序的双向链表,因此提供了按照插入顺序遍历的能力,同时保证了常数时间的添加、删除、contains等操作,这些操作性能略低于HashSet,因为需要维护链表的开销。
  • 遍历元素时,HashSet性能受自身容量影响,初始化时,尽量不要使底层HashMap容量太大。LinkedHashSet由于有双链表,遍历性能只和元素多少有关系。

TreeSet

构造函数:

底层构建了一个TreeMap对象。

public TreeSet() {
    this(new TreeMap<E,Object>());
}

public TreeSet(Comparator<? super E> comparator) {
    this(new TreeMap<>(comparator));
}

public TreeSet(Collection<? extends E> c) {
    this();
    addAll(c);
}

public TreeSet(SortedSet<E> s) {
    this(s.comparator());
    addAll(s);
}

TreeSet(NavigableMap<E,Object> m) {
    this.m = m;
}

字段:

    private transient NavigableMap<E,Object> m;
    private static final Object PRESENT = new Object(); // 作为TreeMap的Value

元素操作:

从源码可知,就是在调用TreeMap的操作方法。

public boolean add(E e) {
    return m.put(e, PRESENT)==null;
}

public boolean remove(Object o) {
    return m.remove(o)==PRESENT;
}

迭代器:

TreeSet中的TreeMap是按照插入顺序构建的双链表,iterator方法返回的是TreeMap的KeyIterator迭代器,descendingIterator方法返回的是TreeMap的DescendingKeyIterator迭代器。所以支持按插入顺序的正向和反向迭代。

public Iterator<E> iterator() {
    return m.navigableKeySet().iterator();
}

public Iterator<E> descendingIterator() {
    return m.descendingKeySet().iterator();
}

HashSet

构造函数:

    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);
    }

字段:

    private transient HashMap<E,Object> map;

    // 仅仅用来充当Map的Value,没有实际意义
    private static final Object PRESENT = new Object();

方法举例:

    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }

    public boolean remove(Object o) {
        return map.remove(o)==PRESENT;
    }

LinkedHashSet

是HashSet的子类,且没有重写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的构造方法,这个构造方法的访问权限是package,使得LinkedHashSet的底层数据结构为LinkedHashMap。

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


上一篇:JDK1.8并发之生产者消费者问题
下一篇:无

猜你喜欢

转载自blog.csdn.net/weixin_40255793/article/details/80791861