List接口常用实现类

ArrayList的实现:

  话不多说,直接看源码:

 

 

   这句话是这样描述的,它是List的实现类,并且是一个可变的数组。实现了List所有的操作,允许存放所有元素,包括空。除了实现List接口外,这个类还提供了操作数组大小的方法,意思集合的长度是可以改变的。最后还提到了这个类和Vector类似,只是不是同步的。很多人都说ArrayList会给一个初始大小,我们通过源码来看看这样的说法到底准确不,当我们创建一个ArrayList的时候,我们看看做了什么:

 

 

 这里将elementData赋值为DEFAULTCAPACITY_EMPTY_ELEMENTDATA,继续看看它们分别是什么。

 

 

   看上面的注释,重点是后面两句话当添加第一个元素时,任何带有elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA 的空ArrayList将扩展为DEFAULT_CAPACITY。

 

 

 

 

 

   从注释的描述来看,我们上面说的会有一个初始化的大小貌似没有错,并且大小为10,但是注释里面描述的是将要扩展为10,并没有说在初始化的时候设置为10,我们看构造器里面,只是将其设置为了一个空的数组,所以并不是在初始化的时候给它设置的初始长度。那么到底什么时候设置的呢,我们继续来看,当创建好一个ArrayList对象之后,我们肯定要添加元素到该对象中,所以我们来看add方法:

 

 

   进入ensureCapacityInternal方法,这里传了一个参数,size初始值为0,所以相当于传了一个1进去:

 

 

   再来看calculateCapacity方法,这个方法传了两个参数,一个是创建对象的时候设置的一个ArrayList的一个缓存集合,它现在是一个空数组,还有一个就是上面传进来的1:

 

 

   这个方法逻辑很简单,如果elementData为空集合,即说明是第一次进行添加操作,我们就比较传进来的长度和默认的10,返回大的,所以这里我们也明白了传进来的int数字其实就是自定义的集合长度值,只是这里我们没有选择自定义,所以默认是1.。如果不是第一次的话,则直接返回传进来的长度。再来看ensureExplicitCapacity方法

 

 

   最终调用了grow方法,来看这个方法的实现:

 

 

 

 

  具体细节逻辑这里就不详细描述了,主要注意圈起来的两个地方,可以得到ArrayList的扩容是每次扩容1.5倍,而具体扩容的原理是通过数组的复制实现的。

  根据上面的源码分析,我们可以得到如下结论:

  • ArrayList的底层是通过数组实现的。
  • ArrayList如果在初始化的时候没有指定长度,那么在使用的时候即调用add方法的时候会设置一个默认的长度10。
  • ArrayList装满的时候,程序会自动扩容,扩容至之前的1.5倍。
  • ArrayList和Vector十分类似,区别就在于ArrayList是线程不安全的,而Vector是线程安全的。

LinkedList的实现:

  老规矩,直接看类的注释:

 

   从上面的描述可以得到LinkedList底层是通过双向链表实现的,可以保存空值,同样它不是线程安全的。

LinkedList的源码非常简单,这里就不介绍了。

Vector的实现:

  Vector实现和ArrayList基本上是一致的,唯一的区别就是它是线程安全的,所以效率相较于ArrayList低。

总结:

  ArrayList:实现了长度可变的数组,在内存中分配连续的空间。

  优点:遍历元素和随机访问元素的效率较高。

  缺点:添加和删除需要大量移动元素,效率低,按照内容查找效率低。

  LinkedList:采用双向链表存储方式。

  优点:插入、删除元素效率较高。

  缺点:遍历和随机访问元素效率较低。

  

posted @ 2020-12-08 22:44  负重前行的小牛  阅读(199)  评论(0编辑  收藏  举报