在端午节这个节日里,有一个特殊的任务,我带着你一起揭开“ArrayList”的真面目。从成员变量、构造函数、主要方法三部分,对ArrayList有进一步的认识,希望能够帮助你。

一、成员变量

   //默认容量
private static final int DEFAULT_CAPACITY = 10;
//空数组,当调用无参数构造函数的时候默认给个空数组
private static final Object[] EMPTY_ELEMENTDATA = {};
//真正保存数据的数组
private transient Object[] elementData;
//数组的大小
private int size;

transient关键字:ArrayList实现了Serializable接口,而添加上transient关键字,则elementData对象就不可以序列化。

二、构造函数

  • 无参构造方法

  • 带有容量的构造方法

  • 带参数Collection的构造方法

在参数Collection的构造方法中,只有当当得到的elementData的类名不是Object,才会执行复制操作,因为Java是动态绑定,所以getClass获取的并不一定是Object类型,有可能是它的子类。

/**
* 初始化elementData
* @param initialCapacity
*/
public ArrayList(int initialCapacity) {
super();
//如果小于0,则抛出异常
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
//初始化elementData数组
this.elementData = new Object[initialCapacity];
} /**
* 初始化为空的对象数组
*/
public ArrayList() {
super();
this.elementData = EMPTY_ELEMENTDATA;
} public ArrayList(Collection<? extends E> c) {
//将c容器转换为object类型的数组
elementData = c.toArray();
//更新size的大小
size = elementData.length;
//当得到的elementData的类名不是Object,才会执行复制操作
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
}

三、主要方法

1、add方法

//添加元素
public boolean add(E e) {
//首先判断数组容量是否需要扩充
ensureCapacityInternal(size + 1); // Increments modCount!!
//添加元素,更新size的大小
elementData[size++] = e;
return true;
}

ArrayList相当于在没指定initialCapacity时就是会使用延迟分配对象数组空间,当第一次插入元素时ensureCapacityInternal,才分配10个对象空间。

2、get方法

 //通过下标获取元素
public E get(int index) {
//判断下标的合理性
rangeCheck(index);
//返回元素
return elementData(index);
}

3、remove方法

在remove方法中,我们需要注意对null的特殊处理。

public boolean remove(Object o) {
//如果为null对象,则特殊处理,使用==来判断
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
//如果不为null,则使用equals方法来判断。
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}

四、其他常用的方法

removeAll:移除集合A和集合B的交集,即A-B。

retainAll:保留两个集合的交集。

五、ArrayList的大小是如何自动增加的?(面试题)

  • ensureCapacityInternal    是判断是否要扩容的方法

  • ensureExplicitCapacity

  • grow 具体的扩容方法

实现思想:

  1. 确定所需minCapacity和数组当前size的关系,如果minCapacity>size,则准备grow。

  2. 如果1.5size<minCapacity,则准备扩充为minCapacity。

  3. minCapacity和MAX_ARRAY_SIZE 的关系,如果minCapacity>MAX_ARRAY_SIZE ,则需要判断minCapacity是否超出int类型所能表示的最大值。如果超出,则抛出OutOfMemoryError。

 //确保数组能够存放的:minCapacity
private void ensureCapacityInternal(int minCapacity) {
//如果elementData是空对象数组,最小容量为minCapacity和DEFAULT_CAPACITY最大值
if (elementData == EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
//判断是否需要扩容
ensureExplicitCapacity(minCapacity);
} private void ensureExplicitCapacity(int minCapacity) {
//增加被改变的次数
modCount++;
// 最小容量大于elementData的长度,则需要扩充
if (minCapacity - elementData.length > 0)
grow(minCapacity);
} //数组的最大上限
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; private void grow(int minCapacity) {
// 数组原来的长度,保存副本
int oldCapacity = elementData.length;
//扩容至原来的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
//判断新容量是否够用,如果不够则赋值为minCapacity
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//如果newCapacity超过MAX_ARRAY_SIZE
if (newCapacity - MAX_ARRAY_SIZE > 0)
//检查容量的int值是不是已经溢出。
newCapacity = hugeCapacity(minCapacity);
// 调用Arrays.copyOf方法将elementData数组指向新的内存空间时newCapacity的连续空间
// 并将elementData的数据复制到新的内存空间
elementData = Arrays.copyOf(elementData, newCapacity);
} private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}

欢迎加入Java学习交流群点击:484757838 

ArrayList源码解读的更多相关文章

  1. ArrayList 源码解读

    ArrayList 源码解读     基于JDk 1.7.0_80 public class ArrayList<E> extends AbstractList<E> impl ...

  2. JDK12下的ArrayList源码解读 与 Vector的对比

    ArrayList源码阅读. //测试代码实现如下 private static void arrayList() { ArrayList<String> list = new Array ...

  3. ArrayList源码解读(jdk1.8)

    概要 上一章,我们学习了Collection的架构.这一章开始,我们对Collection的具体实现类进行讲解:首先,讲解List,而List中ArrayList又最为常用.因此,本章我们讲解Arra ...

  4. 深入理解JAVA集合系列四:ArrayList源码解读

    在开始本章内容之前,这里先简单介绍下List的相关内容. List的简单介绍 有序的collection,用户可以对列表中每个元素的插入位置进行精确的控制.用户可以根据元素的整数索引(在列表中的位置) ...

  5. Java集合ArrayList源码解读

    最近在回顾数据结构,想到JDK这样好的代码资源不利用有点可惜,这是第一篇,花了心思.篇幅有点长,希望想看的朋友认真看下去,提出宝贵的意见.  :) 内部原理 ArrayList 的3个字段 priva ...

  6. java集合之ArrayList源码解读

    源自:jdk1.8.0_121 ArrayList继承自AbstractList,实现了List.RandomAccess.Cloneable.Serializable. ArrayList内部是通过 ...

  7. ArrayList源码解读笔记

    简介: ArrayList是我们开发中非常常用的数据存储容器之一,其底层是数组实现的,我们可以在集合中存储任意类型的数据,ArrayList是线程不安全的,非常适合用于对元素进行查找,效率非常高. 线 ...

  8. Java集合(四)--基于JDK1.8的ArrayList源码解读

    public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess ...

  9. jdk1.8.0_45源码解读——ArrayList的实现

    jdk1.8.0_45源码解读——ArrayList的实现 一.ArrayList概述 ArrayList是List接口的可变数组的实现.实现了所有可选列表操作,并允许包括 null 在内的所有元素. ...

随机推荐

  1. ios 渐进淡出

    在github上寻找的经典demo //以view为继承类 LazyFadeInView-master https://github.com/itouch2/LazyFadeInView //以Lab ...

  2. 转账示例(一):Dao层面实现(本例采用QueryRunner来执行sql语句,数据源为C3P0)

    缺点:Dao层面把Service层面的操作完成了,不利于后期的代码修改和重构 1.自行创建C3P0Util account数据库 2.jar包 3.Dao层面 接口: package com.lear ...

  3. ecshop打开手机端QQ对话窗口

    ecshop的手机功能比较弱,默认的模板很丑,也不带打开手机端QQ等功能,在程序里添加im等程序变量后,在模板里引入以下代码,即可打开手机端qq对话窗口 <!-- QQ 号码 {foreach ...

  4. Java --- JSP2新特性

    自从03年发布了jsp2.0之后,新增了一些额外的特性,这些特性使得动态网页设计变得更加容易.jsp2.0以后的版本统称jsp2.主要的新增特性有如下几个: 直接配置jsp属性 表达式语言(EL) 标 ...

  5. 深入理解css中vertical-align属性

    一.为什么要写这篇文章 今天看到一个问题: 两个div 都设置 display:inline-block,正常显示:但是在第二个div中加一个块级元素或者内联元素,显示就变了个样,为什么? <m ...

  6. sql连接查询中on筛选与where筛选的区别

    sql查询这个东西, 要说它简单, 可以很简单, 通常情况下只需使用增删查改配合编程语言的逻辑表达能力,就能实现所有功能. 但是增删查改并不能代表sql语句的所有, 完整的sql功能会另人望而生畏. ...

  7. OutOfMemoryError内存不足

    java.lang.OutOfMemoryError内存不足错误.当可用内存不足以让Java虚拟机分配给一个对象时抛出该错误. 造成此错误的原因有一下几个: 1.内存中加载的数据量过于庞大,如一次从数 ...

  8. 概率检索模型及BM25

    概率排序原理 以往的向量空间模型是将query和文档使用向量表示然后计算其内容相似性来进行相关性估计的,而概率检索模型是一种直接对用户需求进行相关性的建模方法,一个query进来,将所有的文档分为两类 ...

  9. .net 读取实体属性和描述注释

    .net 读取实体属性和描述注释 class Program { static void Main(string[] args) { TEST test = new TEST(); test.MyNa ...

  10. Eclipse实现图形化界面插件-vs4e

    vs4e插件下载地址:http://visualswing4eclipse.googlecode.com/files/vs4e_0.9.12.I20090527-2200.zip 下载完成后,解压,然 ...