美文网首页
Java集合--List及其实现类

Java集合--List及其实现类

作者: 小明今晚加班 | 来源:发表于2019-05-22 19:47 被阅读0次

List集合存放的元素是有序,可重复的。
文档定义如下:

public interface List<E> extends Collection<E> {}

List继承了Collection<E>接口,由于集合中存放的都是对象,因此List对象在add操作的时候可以add(null)。


这里主要介绍List的三个实现类ArrayList、LinkedList、Vector。
先给出它们三个的定义:

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable{}
public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable{}
public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable{}

从它们各自的定义我们能发现ArrayList和Vector都实现了List<E>接口,这也是我们平时总是定义列表的时候习惯写List<E> list = new ArrayList<>();同时,我们还发现二者都实现了RandomAccess接口,而LinkedList没有实现RandomAccess接口,RandomAccess接口的目的就是告诉我们,实现了该接口的类支持高速随机访问。(当查阅RandomAccess定义的时候,我们发现RandomAccess只是定义了一下,内部并没有任何的方法,我猜这里可能就是为了标识一下吧,标识 -- 实现了该接口的类都支持高速随机访问[当然最可靠的办法还是看源码])
从另一角度还可以分析ArrayList和Vector支持高速随机访问,而LinkedList不支持。ArrayList和Vector底层是通过数组实现,LinkedList底层是通过双向链表实现。我们知道数组的优点是读取方便,即可以通过索引直接读取值,而链表的读取需要从前向后依次查找,但是链表的删除和插入方便。因此这里最能解释为什么ArrayList和Vector支持高速随机访问,而LinkedList不支持。

ArrayList和Vector的区别是什么呢?
ArrayList中方法都没有做同步,因此ArrayList是线程不安全的;Vector中方法基本都做了同步,因此是线程安全的。我们知道同步是高损耗的,平时尽可能的不去使用同步,除非业务需要,比如转账操作。这也能解释我们平时定义列表的时候为啥总是习惯写List<E> list = new ArrayList<>();首先没有同步机制,低耗;另一个平时大多数情况下都是读操作居多。

下面以列表的add方法为例,查看一下源码,拿ArrayList和LinkedList对比分析:(ArrayList和Vector在源码中区别就在于有没有关键字synChronized,这里就不分析了)

ArrayList中的add()方法
   /**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        //1、判断数组容量是否够用 2、赋值 3、return
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

继续看ensureCapacityInternal()的源码:

    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
    //主要是ensureExplicitCapacity方法
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;//这个modCount变量的作用是计数,记录修改次数(发现:变量modCount经常出现在线程不安全的方法中)

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

再继续看grow方法:

   /**
     * Increases the capacity to ensure that it can hold at least the
     * number of elements specified by the minimum capacity argument.
     *
     * @param minCapacity the desired minimum capacity
     */
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        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:
        //我们看到这里使用了数组的复制方法,进而实现列表的add方法
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
LinkedList中的add方法
   /**
     * Appends the specified element to the end of this list.
     *
     * <p>This method is equivalent to {@link #addLast}.
     *
     * @param e element to be appended to this list
     * @return {@code true} (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        linkLast(e);
        return true;
    }

继续看linkLast方法:

   /**
     * Links e as last element.
     */
    void linkLast(E e) {
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
    }

继续看Node的定义:

private static class Node<E> {
        //当前节点
        E item;
        //当前节点的后节点
        Node<E> next;
        //当前节点的前节点
        Node<E> prev;

        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }

从最后看出,LinkedList因为使用了双向链表,插入和删除都很方便。

相关文章

  • Java集合--List及其实现类

    List集合存放的元素是有序,可重复的。文档定义如下: List继承了Collection接口,由于集合中存...

  • 2018-08-08

    java集合类的底层实现 LinkedList底层实现和原理 LinkedList类是List接口的实现类,它是一...

  • Java集合

    Java中的集合有两类:一类是Collection接口集合,实现有List和Set;还有一类是Map接口集合,实现...

  • kotlin中的集合

    集合Java中常用的集合主要是List、Set和Map接口,List的实现类是ArrayList和LinkedLi...

  • ArrayList&LinkedList源码分析

    引言 基于Java集合框架图,本文针对List集合的主要实现类 ArrayList和LinkedList从...

  • Android面试Java基础篇(一)

    问:Java集合类List,Map,Set相关的实现原理。 答:List和Set都是Collection的子类 ...

  • Java中的List你真的会用吗?

    List是Java中比较常用的集合类,关于List接口有很多实现类,本文就来简单介绍下其中几个重点的实现Array...

  • Java中的List总结

    List是Java中比较常用的集合类,关于List接口有很多实现类,本文就来简单介绍下其中几个重点的实现Array...

  • ArrayList 与 LinkedList的性能区别

    Java集合类 Set:无序、不可重复;List有序、重复的集合;Queue代表队列集合实现;Map代表具有映射关...

  • Java基础(五)

    Java集合 接口继承关系和实现 集合类存放于 Java.util 包中,主要有 3 种:set(集)、list...

网友评论

      本文标题:Java集合--List及其实现类

      本文链接:https://www.haomeiwen.com/subject/bqfpzqtx.html