深入理解JAVA集合系列四:ArrayList源码解读
在开始本章内容之前,这里先简单介绍下List的相关内容。
List的简单介绍
有序的collection,用户可以对列表中每个元素的插入位置进行精确的控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。列表通常允许重复的元素,且允许null元素的存放。
ArrayList的简单介绍
JDK中这样定义ArrayList:List接口的大小可变数据的实现。
主要有以下特点:
1、有序
2、线程不安全
3、元素可以重复
4、可以存放null值
顾名思义,取名ArrayList是因为其内部是用一个大小可变的数组存储元素,也就是说底层是一个动态数组。
add方法解读
List<String> li = new ArrayList<String>();
li.add("33");
先看这个构造函数:
public ArrayList() {
this(10);
}
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
}
这里先定义默认的初始容量为10,然后构建了一个容量为10的数组elementData;这个elementData数组就是ArrayList底层存放元素的数组,且元素是Object类型。该数组的源码定义也了解下:
private transient Object[] elementData;
再来看ADD方法:
public void add(int index, E element) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(
"Index: "+index+", Size: "+size);
ensureCapacity(size+1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
1、第6行的扩容部分后面再解释,其余的比较简单,我们直接看第7行。调用的是System.arraycopy的方法。
2、第一次看到这个方法有点搞不懂,先来解释下:System.arraycopy(src, srcPos, dest, destPos, length);
第一个参数表示的是要被复制的数组;第二个参数表示数组中从第几个元素开始复制。
第三个参数表示复制到哪个数组;第四个参数表示复制到那个数组从哪个元素开始;第五个参数表示要复制的长度
3、解释完这个方法就很清楚了,add方法就是将数组中待添加元素的位置后面所有的元素(包括该位置),通过copy的复制方法,全部后移一个位置。然后将待添加的元素放到指 定的位置上。当然这个数组可能是原数组,也可能是经过第6行代码扩容之后新的数组。
扩容
扩容,动态扩容,也就是前面所提到的ArrayList的底层是由一个动态变化的数组实现的。
public void ensureCapacity(int minCapacity) {
modCount++;
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3)/2 + 1;
if (newCapacity < minCapacity)
newCapacity = minCapacity;
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
1、我们看扩容的算法,也就是在旧容量的基础上,扩大1.5倍再加上1。至于为什么是这样一个算法,我也没明白。但是JDK开发人员肯定是在这方面做过思考的:不能一次性扩容太大,会造成内存空间的浪费;也不能扩容得不够,否则下一次扩容的操作会很快到来。我猜想应该是基于这样的考虑才设计了这样一个算法。
2、扩容结束后,就是将旧数组里面的元素全部复制到新的数组里。并且新数组还是通过elementData变量来引用。
remove方法解读
我们先来看下该方法的源码:
public E remove(int index) {
RangeCheck(index);
modCount++;
E oldValue = (E) elementData[index];
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
return oldValue;
}
其实这个remove的方法处理的过程也比较简单:
1、第2行代码是用来检测数组下标是否越界。
2、然后取出该位置上的数组元素。
3、通过arryCopy方法将待删除元素之后的所有元素往前一个位置复制。(注意,这个动作是先复制,然后粘贴)。
4、这个时候最后一个位置上的元素就是多余的,所以才有了第11行的处理,将其置为null。
ArrayList的优缺点
1、底层是由数组实现的,便于随机访问。
2、顺序添加元素性能比较高,相当于每次在数组最后添加一个元素、
3、插入元素、删除元素的时候,会涉及到元素的复制,即调用arrayCopy方法,如果复制的元素比较多,则这样就比较消耗性能。
总结来说:ArrayList的优势是随机访问、顺序添加。
深入理解JAVA集合系列四:ArrayList源码解读的更多相关文章
- java集合系列之ArrayList源码分析
java集合系列之ArrayList源码分析(基于jdk1.8) ArrayList简介 ArrayList时List接口的一个非常重要的实现子类,它的底层是通过动态数组实现的,因此它具备查询速度快, ...
- Java集合系列[1]----ArrayList源码分析
本篇分析ArrayList的源码,在分析之前先跟大家谈一谈数组.数组可能是我们最早接触到的数据结构之一,它是在内存中划分出一块连续的地址空间用来进行元素的存储,由于它直接操作内存,所以数组的性能要比集 ...
- Java集合系列[4]----LinkedHashMap源码分析
这篇文章我们开始分析LinkedHashMap的源码,LinkedHashMap继承了HashMap,也就是说LinkedHashMap是在HashMap的基础上扩展而来的,因此在看LinkedHas ...
- java集合系列之HashMap源码
java集合系列之HashMap源码 HashMap的源码可真不好消化!!! 首先简单介绍一下HashMap集合的特点.HashMap存放键值对,键值对封装在Node(代码如下,比较简单,不再介绍)节 ...
- java集合系列之LinkedList源码分析
java集合系列之LinkedList源码分析 LinkedList数据结构简介 LinkedList底层是通过双端双向链表实现的,其基本数据结构如下,每一个节点类为Node对象,每个Node节点包含 ...
- Java集合系列[3]----HashMap源码分析
前面我们已经分析了ArrayList和LinkedList这两个集合,我们知道ArrayList是基于数组实现的,LinkedList是基于链表实现的.它们各自有自己的优劣势,例如ArrayList在 ...
- 【java集合总结】-- ArrayList源码解析
一.前言 要想深入的了解集合就必须要通过分析源码来了解它,那如何来看源码,要看什么东西呢?主要从三个方面: 1.看继承结构 看这个类的继承结构,处于一个什么位置,不需要背记,有个大概的感觉就可以,我自 ...
- Java集合系列:-----------03ArrayList源码分析
上一章,我们学习了Collection的架构.这一章开始,我们对Collection的具体实现类进行讲解:首先,讲解List,而List中ArrayList又最为常用.因此,本章我们讲解ArrayLi ...
- Java集合系列[2]----LinkedList源码分析
上篇我们分析了ArrayList的底层实现,知道了ArrayList底层是基于数组实现的,因此具有查找修改快而插入删除慢的特点.本篇介绍的LinkedList是List接口的另一种实现,它的底层是基于 ...
随机推荐
- 20155325 2017-2018 1 课上测试、课下作业、实验——码云&博客链接汇总 《信息安全系统设计基础》
第二周-课上 码云 https://gitee.com/bestiisjava2017/XinXiAnQuanXiTongSheJiJiChu20155325thl/tree/master/0927 ...
- 15-[JavaScript]-ECMAScript 1
0.javaScript的发展历程 https://zhuanlan.zhihu.com/p/27985124 1.javaScript是什么? javaScript是一种web前端的描述语言,也是一 ...
- 5 admin的使用
1.admin组件的使用 Django 提供了基于 web 的管理工具. Django 自动管理工具是 django.contrib 的一部分.你可以在项目的 settings.py 中的 INSTA ...
- Eclipse中Applet程序运行时Applet小程序大小的设置
最近在跟斯坦福的CS106A,里面的java代码都是Applet程序,而我运行程序的时候发现,Applet小程序窗口大小总是固定的,但是我画的图却越来越大,所以怎么在Eclipse中run的时候 ...
- CI/CD系列
一.CI/CD系列 什么是CI/CD(译) Docker与CI/CD(转) Docker和CI/CD实战 二.Git 三.GitLab
- 使用 Django WebSocket Redis 搭建在线即时通讯工具
话不多说先上效果图演示 项目:http://112.74.164.107:9990/ 1.安装组建 redis: yum install redis/apt install redis 2.创建虚拟化 ...
- 2018年美国大学生数学建模竞赛(MCM/ICM) C题解题思路
整个赛题是一道大数据的深层挖掘与分析赛题,数据在这是很重要的组成因 素,因此大家首先应该把题目所给的数据搞清楚搞明白.赛题的关键是能源生产 和使用的合理安排,针对第一部分,主要解决能源的配置与评价问题 ...
- XSS分类&危害&防御
XSS(跨站脚本)漏洞是什么? 在网页中插入恶意的js脚本,由于网站没对其过滤,当用户浏览时,就会触发脚本,造成XSS攻击 XSS分类? 1.反射型 用户输入的注入代通过浏览器传入到服务器后,又被目标 ...
- linux 下awk后统计某一列数据之和简单的命令
例如有文件test.txt格式如下: aaa:1 bbb:2 cat a|awk -F\: '{print"+"$2}'|xargs echo 0|bc -l
- C#如何在各类控件中输入\输出数据
文本框:TextBox Text - 按钮文字 TextBox.text=""; s=TextBox.text; 单选按钮+复选按钮 RadioButton,CheckBox Te ...