天天看点

Java容器之Collection

   Java中容器主要分为两大类:Collection和Map,让我们来看一下Collection下主要的继承类和实现类。

Java容器之Collection

   1)List:是一个有序的队列,主要实现类如下图所示。

Java容器之Collection

   其中,ArrayList基于动态数组实现,支持随机访问,但是增加和删除需要移动数据,是线程不安全的;LinkedList是以双向链表实现,随机访问需要移动指针,增加删除操作不需要移动数据,允许重复,是线程不安全的;Vector基于动态数组实现,是线程安全的。

   2)Queue:主要实现类如下图所示。

Java容器之Collection

   其中,PriorityQueue是基于堆结构实现,可以实现优先队列,线程不安全;LinkedList可以实现双向队列。

   3)Set:是一种不允许数据元素重复的集合,无序,主要实现类及接口如下图所示。

Java容器之Collection

   其中,HashSet实现Set接口,线程不安全,由哈希表(实际上是一个HashMap的实例)实现,底层是一个HashMap来保存HashSet中的所有元素,允许null值;LinkedHashSet继承HashSet,源码中其构造方法直接调用父类(HashSet)的构造方法,而父类的构造方法是HashMap实现所以LinkedHashSet也是HashMap实现的,线程不安全;

   这里要说一下TreeSet,它是AbstractSet接口的一个实现类,它的底层实现是TreeMap,而TreeMap的实现又借助了HashMap,所以,HashMap真的太重要了!TreeSet中元素是有序且不重复的,线程不安全,这里的有序是指按照关键字大小进行排序,实现原理是使用了比较器,源码如下:

/**
 * Constructs a new, empty tree set, sorted according to the specified
 * comparator.  All elements inserted into the set must be <i>mutually
 * comparable</i> by the specified comparator: {@code comparator.compare(e1,
 * e2)} must not throw a {@code ClassCastException} for any elements
 * {@code e1} and {@code e2} in the set.  If the user attempts to add
 * an element to the set that violates this constraint, the
 * {@code add} call will throw a {@code ClassCastException}.
 *
 * @param comparator the comparator that will be used to order this set.
 *        If {@code null}, the {@linkplain Comparable natural
 *        ordering} of the elements will be used.
 */
 public TreeSet(Comparator<? super E> comparator) {
    this(new TreeMap<>(comparator));
 }
           

   总结一下ArrayList和LinkedList的异同点:首先,两者都是线程不安全的;ArrayList是基于动态数组实现的,LinkedList基于链表的数据结构;对于随机访问,ArrayList优于LinkedList,因为LinkedList要移动指针;对于增加和删除操作,LinkedList要好一些。

   总结一下ArrayList和Vector的异同点:ArrayList线程不安全,而Vector是线程安全的;在进行扩容操作时,ArrayList每次resize为当前的1.5倍,而Vector每次扩大2倍(如下源码所示)

   ArrayList扩容

private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    //扩大为原来的1.5倍,因为oldCapacity >> 1 相当于 oldCapacity / 2
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
 }
           

   Vector扩容

private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                     capacityIncrement : oldCapacity);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    elementData = Arrays.copyOf(elementData, newCapacity);
  }
           

继续阅读