欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

List --- ArrayList源码解析

程序员文章站 2024-01-03 09:02:40
...

 

本文采用的是jdk1.8,分析ArrayList常用的方法源码

 

一,ArrayList的关系图

List --- ArrayList源码解析

在我们日常开发阶段,ArrayList是我们用的非常非常多的一个集合,带来了很大的便利,下面开始分析ArrayList的源码

 

二,源码分析

2.1属性分析

List --- ArrayList源码解析

从ArrayList的属性,我们可以很清楚的看出:ArrayList的底层就是一个数组的形式,ArrayList中有扩容的概念,正式因为有扩容,所有它能实现动态增长

 

2.2 构造方法

List --- ArrayList源码解析

 

2.3 add方法

add()方法是我们常用的方法,可以说是ArrayList比较重要的方法了,下面我们来看看:

List --- ArrayList源码解析

2.3.1 add(E e)

步骤:

  • 检查是否需要扩容
  • 插入元素

首先先看看这个方法

 public boolean add(E e) {
        //确定list的容量,尝试容量加1
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        //添加元素
        elementData[size++] = e;
        return true;
    }

这个方法主要就是干两件事:

  • 确定list的容量,尝试容量+1,看有没有扩容的必要
  • 添加元素

接下来进入ensureCapacityInternal()方法,看看容量的的添加过程

List --- ArrayList源码解析

随后调用ensureExplicitCapacity()来确定明确的容量,我们也来看看这个方法是怎么实现的:

List --- ArrayList源码解析

接下来看看grow()对数组的扩容过程

List --- ArrayList源码解析

进入copyOf()方法看看是如何移动数组的

List --- ArrayList源码解析

我们再进入arraycopy()里看看

List --- ArrayList源码解析

该方法带有native修饰符,就可以知道是C/C++去写的,并非java来实现的,总的来说arraycopy()是一个比较高效可靠的方法

 

到目前为止,我们可以知道add(E e)的基本实现了:

>>首先去检查一下数组的容量是否足够

>>>>足够,直接添加元素

>>>>不足够,扩容数组

>>>>>>扩容都原来的1.5倍

>>>>>>第一次扩容后,如果容量还是小于minCapacity,就将容量扩充为minCapacity

 

2.3.2 add(int index, E element)

步骤:

  • 检查角标
  • 检查是否需要扩容
  • 插入元素

下面这个是插入的实现:

List --- ArrayList源码解析

 

2.4 get()

步骤:

  • 检查角标
  • 返回元素

List --- ArrayList源码解析

接下来我们看看rangeCheck()和elementData()两个方法:

List --- ArrayList源码解析

List --- ArrayList源码解析

 

2.5  set(int index, E element)

步骤:

  • 检查角标
  • 替代元素
  • 返回旧值

List --- ArrayList源码解析

 

2.6 remove(int index)

步骤

  • 检查角标
  • 计算要移动的个数,并移动
  • 将最后一个元素设为null(删除),让gc进行回收

 

List --- ArrayList源码解析

 

2.7 细节说明

  • ArrayList是基于动态数组实现的,在增删时候,需要数组的拷贝复制
  • ArrayList的默认初始化容量是10,每次扩容时候增加原先容量的一半,也就是变为原来的1.5倍
  • 删除元素时不会减少容量,若希望减少容量则调用trimToSize()
  • 它不是线程安全的。它能存放null值。

 

相关标签: 源码分析

上一篇:

下一篇: