前言

ArrayList想必是广大Java程序员开发时最常用的数据结构了,但不一定对其原理都有了解,今天我将结合ArrayList的源码对其进行讲解。本文将围绕ArrayList主要特性(包括适用场景、初始大小、扩容等)、数据存放方式、核心方法实现、其他特性等四个方面进行讲解。

一、ArrayList特性

ArrayList是基于数组的数据结构,与LinkedList相比,更加适合在查询多、增删操作少的场景下使用,并且它是非线程安全的,如果并发量比较大的场景,需要改用线程安全的版本或者用JUC包中的CopyOnWriteArrayList。

它的初始数组大小为10,由下图所示的成员变量控制:

当新加元素时原数组已经满了,则会触发扩容,扩容策略为将原数组长度*1.5,代码中是用右移位运算实现的,源码如下所示:

二、数据存放方式

ArrayList是以数组的方式存放数据的,Object[],如下所示:

三、核心方法实现

我们看最常用的add方法:

 public boolean add(E e) {
ensureCapacityInternal(size + 1); // 如果已经满了,则扩容
elementData[size++] = e;
return true;
}

下面方法用于判断是否原数组已经满了,如果满了则扩容,不满且未初始化则初始化长度为10,否则不用变化

 private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

下面方法用于返回数组需要的最小长度。

 private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}

下面的方法用于判断是否需要扩容,如果需要则通过grow方法扩容。

 private void ensureExplicitCapacity(int minCapacity) {
modCount++; // overflow-conscious code
if (minCapacity - elementData.length > 0) // 如果需要的最小长度大于当前数组总长度,则走grow扩容
grow(minCapacity);
}

下面的grow方法是控制扩容的核心方法:

 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:
elementData = Arrays.copyOf(elementData, newCapacity); // 创建新数组,将老数组的数据复制过去
}

注意复制数组时,用的Arrays.copyOf方法,该方法最终引用的是System.arraycopy这个native方法实现的数组复制。其他方法更加简单,此处就不一一粘贴源码解读了。

四、其他特性

1、关于modCount

在看ArrayList源码的时候,会发现有一个变量是modCount,在增删改的方法中均涉及到对它的++操作。modCount属性是在AbstractList中定义出来的:

可以把它理解成每个ArrayList的一个改动的版本号,只要ArrayList有改动,这个版本号就会+1。在通过迭代器对ArrayList里面的元素进行遍历操作时,每次都会比较一下这个版本号是否有变化,如果检测到预期之外的变化,就会抛出常见的那个异常-ConcurrentModificationException:

ArrayList东西不多,实现也相对比较简单,面试时现在一般会跟Vector或者LinkedList进行比对或者作为多线程的一个引子来问,本文就先到这里,下一期对LinkedList进行解读。

常用数据结构之ArrayList的更多相关文章

  1. JAVA常用数据结构及原理分析

    JAVA常用数据结构及原理分析 http://www.2cto.com/kf/201506/412305.html 前不久面试官让我说一下怎么理解java数据结构框架,之前也看过部分源码,balaba ...

  2. 常用数据结构及复杂度 array、LinkedList、List、Stack、Queue、Dictionary、SortedDictionary、HashSet、SortedSet

    原文地址:http://www.cnblogs.com/gaochundong/p/data_structures_and_asymptotic_analysis.html  常用数据结构的时间复杂度 ...

  3. Java 常用数据结构对象的实现原理 集合类 List Set Map 哪些线程安全 (美团面试题目)

    Java中的集合包括三大类,它们是Set.List和Map, 它们都处于java.util包中,Set.List和Map都是接口,它们有各自的实现类. List.Set都继承自Collection接口 ...

  4. (6)Java数据结构-- 转:JAVA常用数据结构及原理分析

    JAVA常用数据结构及原理分析  http://www.2cto.com/kf/201506/412305.html 前不久面试官让我说一下怎么理解java数据结构框架,之前也看过部分源码,balab ...

  5. 图解Java常用数据结构(一)【转载】

    最近在整理数据结构方面的知识, 系统化看了下Java中常用数据结构, 突发奇想用动画来绘制数据流转过程. 主要基于jdk8, 可能会有些特性与jdk7之前不相同, 例如LinkedList Linke ...

  6. 图解Java常用数据结构(一)

    最近在整理数据结构方面的知识, 系统化看了下Java中常用数据结构, 突发奇想用动画来绘制数据流转过程. 主要基于jdk8, 可能会有些特性与jdk7之前不相同, 例如LinkedList Linke ...

  7. Java 集合框架(常用数据结构)

    早在Java 2中之前,Java就提供了特设类.比如:向量(Vector).栈(Stack).字典(Dictionary).哈希表(Hashtable)这些类(数据结构)用来存储和操作对象组.虽然这些 ...

  8. 【转载】图解Java常用数据结构(一)

    图解Java常用数据结构(一)  作者:大道方圆 原文:https://www.cnblogs.com/xdecode/p/9321848.html 最近在整理数据结构方面的知识, 系统化看了下Jav ...

  9. c#常用数据结构解析【转载】

    引用:http://blog.csdn.net/suifcd/article/details/42869341 前言:可能去过小匹夫博客的盆油们读过这篇对于数据结构的总结,但是小匹夫当时写那篇文章的时 ...

随机推荐

  1. python主线程与子线程的结束顺序

    引用自 主线程退出对子线程的影响--YuanLi 的一段话: 对于程序来说,如果主进程在子进程还未结束时就已经退出,那么Linux内核会将子进程的父进程ID改为1(也就是init进程),当子进程结束后 ...

  2. Rust 入门 (二)

    我认为学习计算机语言,应该先用后学,这一节,我们来实现一个猜数字的小游戏. 先简单介绍一个这个游戏的内容:游戏先生成一个1到100之间的任意一个数字,然后我们输入自己猜测的数字,游戏会告诉我们输入的数 ...

  3. pyinstaller打包python文件成exe(原理.安装.问题)

    py文件打包成exe文件的方式一共有三种:py2exe.PyInstaller和cx_Freeze 本文分四个步骤来详讲如何用PyInstaller将py文件打包成exe文件 1. PyInstall ...

  4. 更好一点的:Vue 利用指令实现禁止反复发送请求

    理论上可以用于任何元素,生效时会在元素上出现一个同大小的灰色蒙层(button元素会该表原生的disabled属性). /** * 当元素触发发起请求后,当发起的请求中最后一个请求的结果返回(不关心返 ...

  5. 【Java并发系列】----JUC之Lock

    显式锁 Lock 在Java 5.0之前,协调共享对象的访问时可以使用的机制只有synchronized和volatile.Java 5.0后增加了一些新的机制,但并不是一种替代内置锁的方法,而是当内 ...

  6. Docker 更换国内的Hub源

    前言 通常情况下,安装的Docker默认使用的是国外的Hub源,在pull镜像的时候很慢,甚至超时了,不动了,很烦人. 更换阿里云Docker的Hub源 阿里云 - 容器Hub服务控制台:https: ...

  7. vsftp安装和配置

    2013-10-10 10:49:48|  分类: Linux|举报|字号 订阅     源码下载地址:ftp://vsftpd.beasts.org/users/cevans/untar/   1. ...

  8. Docker部署Mysql集群

    单节点数据库的弊病 大型互联网程序用户群体庞大,所以架构必须要特殊设计 单节点的数据库无法满足性能上的要求 单节点的数据库没有冗余设计,无法满足高可用 单节点MySQL的性能瓶领颈 2016年春节微信 ...

  9. Kafka use zkCli.sh to check topic offset on linux

    > ./zkCli.sh -server zk1host:port,zk2host:port,zk3host:port >help ZooKeeper -server host:port ...

  10. C语言I博客作业01

    C语言I博客作业01 作业1 这个作业属于哪个课程? C语言程序设计I 这个作业要求在哪里? https://edu.cnblogs.com/campus/zswxy/CST2019-2/homewo ...