ArrayList

  ArrayList 是通过一个数组来实现的,因此它是在连续的存储位置存放对象的引用,只不过它比 Array 更智能,能够根据集合长度进行自动扩容。

  假设让我们来实现一个简单的能够自动扩容的数组,我们最容易想到的点就是:

  1. add()的时候需要判断当前数组size+1是否等于此时定义的数组大小;
  2. 若小于直接添加即可;否则,需要先扩容再进行添加。

实际上,ArrayList的内部实现原理也是这样子,我们可以来研究分析一下ArrayList的源码

add(E e) 源码分析

   /**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 进行扩容校验
elementData[size++] = e; // 将值添加到数组后面,并将 size+1
return true;
} /**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
* will be expanded to DEFAULT_CAPACITY when the first element is added.
*/
transient Object[] elementData; // non-private to simplify nested class access private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); // elementData 数组
} /**
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10; /**
* Shared empty array instance used for default sized empty instances. We
* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
* first element is added.
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; // 返回最大的 index
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { // 与空数组实例对比
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
} private void ensureExplicitCapacity(int minCapacity) {
modCount++; // overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}

扩容调用方法,实际也就是数组复制的过程

     /**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
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);
}

add(int index, E element) 源码分析

   /**
* Inserts the specified element at the specified position in this
* list. Shifts the element currently at that position (if any) and
* any subsequent elements to the right (adds one to their indices).
*
* @param index index at which the specified element is to be inserted
* @param element element to be inserted
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public void add(int index, E element) {
rangeCheckForAdd(index); // 校验index是否超过当前定义的数组大小范围,超过则抛出 IndexOutOfBoundsException ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index); // 复制,向后移动
elementData[index] = element;
size++;
} /**
* A version of rangeCheck used by add and addAll.
*/
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

从上面的源码分析可知,扩容和随机插入元素的消耗比较大,因此在实际开发中,应尽量指定ArrayList大小,减少在随机插入操作。

优缺点

优点

  • 封装了一个动态再分配的对象数组
  • 使用索引进行随机访问效率高

缺陷

  • 在数组中增删一个元素,所有元素都要往后往前移动,效率低下

知识脑图

在 github 上建了一个 repository ,Java Core Knowledge Tree,各位看官若是喜欢请给个star,以示鼓励,谢谢。
https://github.com/suifeng412/JCKTree

(以上是自己的一些见解,若有不足或者错误的地方请各位指出)

作者:那一叶随风   http://www.cnblogs.com/phpstudy2015-6/

原文地址: https://www.cnblogs.com/phpstudy2015-6/p/10618707.html

声明:本博客文章为原创,只代表本人在工作学习中某一时间内总结的观点或结论。转载时请在文章页面明显位置给出原文链接

Java 集合系列(二)—— ArrayList的更多相关文章

  1. Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  2. java集合系列之ArrayList源码分析

    java集合系列之ArrayList源码分析(基于jdk1.8) ArrayList简介 ArrayList时List接口的一个非常重要的实现子类,它的底层是通过动态数组实现的,因此它具备查询速度快, ...

  3. Java集合系列(二):ArrayList、LinkedList、Vector的使用方法及区别

    本篇博客主要讲解List接口的三个实现类ArrayList.LinkedList.Vector的使用方法以及三者之间的区别. 1. ArrayList使用 ArrayList是List接口最常用的实现 ...

  4. java集合系列之三(ArrayList)

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

  5. 【Java集合系列】---ArrayList

    开篇前言--ArrayList中的基本方法 前面的博文中,小编主要简单介绍java集合的总体架构,在接下来的博文中,小编将详细介绍里面的各个类,通过demo.对比,来对java集合类进行更加深入的理解 ...

  6. 【Java集合系列二】LinkedList解析

    一.简介 1.LinkedList继承关系 2.LinkedList底层实现 LinkedList使用双向链表存储数据,所以没有默认的容量,也不会有扩容一说.只有两个指针,永远指向链表的两端:firs ...

  7. Java集合系列[1]----ArrayList源码分析

    本篇分析ArrayList的源码,在分析之前先跟大家谈一谈数组.数组可能是我们最早接触到的数据结构之一,它是在内存中划分出一块连续的地址空间用来进行元素的存储,由于它直接操作内存,所以数组的性能要比集 ...

  8. 深入理解JAVA集合系列二:ConcurrentHashMap源码解读

    HashMap和Hashtable的区别 在正式开始这篇文章的主题之前,我们先来比较下HashMap和Hashtable之间的差异点: 1.Hashtable是线程安全的,它对外提供的所有方法都是都使 ...

  9. Java 集合系列 07 List总结(LinkedList, ArrayList等使用场景和性能分析)

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  10. Java 集合系列 10 Hashtable详细介绍(源码解析)和使用示例

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

随机推荐

  1. C#中为什么会出现空静态构造方法的写法

    再过几个小时,就要回家过春节了,今天说些简单点的东西,大家在看C#代码的时候,一定会对这样的写法非常迷茫:在一个类中会出现一个空的静态构造方法.这不是多此一举吗,这样做的目的是什么?今天我就来说说这个 ...

  2. MySQL 的性能(上篇)—— SQL 执行分析

    简介 文中内容均为阅读前辈的文章所整理而来,参考文章已在最后全指明 本文分为上下两篇: 上篇:MySQL 的 SQL 执行分析 下篇:MySQL 性能优化 后端开发必然会接触到数据库,数据层的优劣会影 ...

  3. 用tensorflow学习贝叶斯个性化排序(BPR)

    在贝叶斯个性化排序(BPR)算法小结中,我们对贝叶斯个性化排序(Bayesian Personalized Ranking, 以下简称BPR)的原理做了讨论,本文我们将从实践的角度来使用BPR做一个简 ...

  4. TypeScript 素描 - 模块、命名空间

    /* 其实前面一些都是废话,因为都和C#类似.从模块开始就需要深入的去理解了 文档反复声明了 内部模块现在称做 命令空间 外部模块称为 模块 模块在其自身的作用域里执行,而不是在全局作用域里,也就是说 ...

  5. Struts2与Spring整合

    前言 本博文主要讲解Spring怎么与Struts2框架整合... Struts2和Spring的整合关键点: action对象交给Spring来创建 搭建环境 进入jar包 引入jar文件: 1)引 ...

  6. ansible学习系列2-ansible常用模块使用

    1. 查看支持的模块 [root@localhost ~]# ansible-doc -l 这里我们看下ansible的支持的模块个数 [root@localhost ~]# ansible-doc ...

  7. python学习第一讲,python简介

    目录 python学习第一讲,python简介 一丶python简介 1.解释型语言与编译型语言 2.python的特点 3.python的优缺点 二丶第一个python程序 1.python源程序概 ...

  8. Cglib动态代理浅析

    原文同步发表至个人博客[夜月归途] 原文链接:http://www.guitu18.com/se/java/2018-06-29/18.html 作者:夜月归途 出处:http://www.guitu ...

  9. C# IQueryable和IEnumerable的区别

    在使用EF查询数据的时候,我们常用的查询数据方式有linq to sql,linq to object, 查询返回的结果有两种类型:IQueryable.IEnumerable,两者内部的处理机制是完 ...

  10. [Go] golang原子函数锁住共享资源

    1.atomic包里的几个函数以及sync包里的mutex类型,提供了解决方案2.原子函数能够以很底层的加锁机制来同步访问整型变量和指针3.atomic.AddInt64(&counter, ...