当前位置:网站首页 > Java基础 > 正文

java基础源码分析



今天要分享的Java集合是List,主要是针对它的常见实现类ArrayList进行讲解
什么是List

List集合是线性数据结构的主要实现,用来存放一组数据。我们称之为:列表。


ArrayList是List的一个常见实现类,它的面试频率和使用频率都非常高,所以我们今天通过学习ArrayList来对Java中的List集合有一个深入的理解。
ArrayList最大的优势是可以将数组的操作细节封装起来,比如数组在插入和删除时要搬移其他数据。另外,它的另一大优势,就是支持动态扩容,这也是我们使用ArrayList的主要场景之一,在某些情况下我们没有办法在程序编译之前就确定存储数据
容器的大小。

核心方法源码剖析

这一部分,选取了ArrayList的一些核心方法进行讲解。分别是:构造方法,add()、和remove()。这里有一个小窍门,我们在读jdk源码的时候,一定要先看类上的doc注释,比较核心的知识点都会写在上面。有一个初步的概念再去看源码,就会容易很多。

1.文档注释

This class is roughly equivalent to Vector, except that it is unsynchronized.
大致相当于Vector,不同之处是不同步(线程不安全)

Implements all optional list operations, and permits all elements, including null
实现所有可选列表操作,并允许所有元素,包括null

2.构造方法

ArrayList()提供了三种构造方法。
ArrayList():构造一个初始容量为10的空列表。
ArrayList(int initialCapacity):构造具有指定初始容量的空列表。
ArrayList(Collection c):构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序。


这里的DEFAULTCAPACITY_EMPTY_ELEMENTDATA是一个空的部数组,不设定初始值时,只是引用这个内部数组。

java基础源码分析


这里的EMPTY_ELEMENTDATA同样是一个空内部数组,为了和DEFAULTCAPACITY_EMPTY_ELEMENTDATA做区分,所以没有使用一个对象。

3.add()

add方法是ArrayList中的一个核心方法,涉及到内部数组的扩容。


该方法是在集合中追加元素。其中核心方法是ensureCapacityInternal,意思是确定集合内部容量。


这里首先计算了集合的容量,如果这个ArrayList是通过无参构造创建的,那么比较默认值10,以及传入的minCapacity,取最大值,这里可能有的同学会有疑问,为什么要比较默认值和minCapacity,默认值不是一定大于minCapacity吗?,这里是因为ensureCapacityInternal这个方法不仅仅是add()会调用,allAll()也会调用。



这里我们主要关注4个点:
1.int newCapacity = oldCapacity + (oldCapacity >> 1);每次扩容是原数组的1.5倍
2.扩容也是有限的,存在最大值:MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8
3.集合扩容底层调用的是:Arrays.copyOf()方法,需要把数组中的数据复制一份,到新数组中,而这个方法底层是System.arrayCopy是一个native方法,效率不高。
4.最重要的一个点:如果我们可以事先估计出数据量,那么最好给ArrayList一个初始值,这样可以减少其扩容次数,从而省掉很多次内存申请和数据搬移操作。(不指定初始值,至少会执行一次grow方法,用于初始化内部数组)。

3.remove()



结果:


产生问题的原因,其实文档注释已经给出了明确的结果,即:
if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own {@link ListIterator#remove() remove} or {@link ListIterator#add(Object) add} methods, the iterator will throw a {@link ConcurrentModificationException}
如果列表在任何时间从结构上修改创建迭代器之后,以任何方式除非通过迭代器自身remove种或add方法,迭代器都将抛出一个ConcurrentModificationException。这里我建议是遍历的时候,不要对其结构进行修改,而是采用其他方法(打标,或者复制列表)的方式进行。

如何提升ArrayList的性能

ArrayList可以代替数组吗?

不可以,任何数据结构都有它存在的场景和意义,集合没有办法存储基本数据类型,只能存储包装类型,包装类型就意味着需要拆箱和装箱,会有一定的性能消耗,如果对性能要求非常高的系统,或者只需要使用基本类型,那么就应该去使用数组而不是集合。同时数组在表示多维数据的时候,也更加直观,比如二维 int[][] 、ArrayList

版权声明


相关文章:

  • java基础入门阶段2024-10-20 17:26:02
  • 0基础学java知乎2024-10-20 17:26:02
  • java语言基础练习32024-10-20 17:26:02
  • java基础编程168单例2024-10-20 17:26:02
  • 张孝祥java基础书籍2024-10-20 17:26:02
  • java基础语法练习52024-10-20 17:26:02
  • 写一个基础的java bean2024-10-20 17:26:02
  • 用Java基础写ATM运作程序2024-10-20 17:26:02
  • java基础面试和sql及答案2024-10-20 17:26:02
  • c语言基础与java哪个难2024-10-20 17:26:02