ArrayList概述

ArrayList继承了AbstractList,实现了List接口,底层基于动态数组,容量大小可以动态变化,ArrayList中可以添加null元素,另外,ArrayList是非线程安全的

ArrayList实现List, RandomAccess, Cloneable, java.io.Serializable接口。

  • 实现RandomAccess接口,即标识着该类支持快速随机访问
  • 实现Cloneable接口,即覆盖了clone(),能被克隆
  • 实现Serializable接口,即ArrayList支持序列化,能被序列化去传输

ArrayList源码分析(基于jdk1.8)


成员变量

    /**
* 默认容量为10
*/
private static final int DEFAULT_CAPACITY = 10;
/**
*存储ArrayList元素的数组缓冲区,ArrayList的容量是此数组缓冲区的长度。
*添加第一个元素时,任何带有elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA的空ArrayList都将扩展为默认容量
*/
transient Object[] elementData;
/**
* ArrayList实际的元素个数
*/
private int size;

构造方法

    /**
构造一个容量大小为10的空list,实际在第一次添加元素时才扩容到10
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
/**
* 构造具有指定初始容量的空的list
*/
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
} //构造一个包含指定 collection 的元素的列表,这些元素是按照该 collection 的迭代器返回它们的顺序排列的
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}

添加操作

    public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
} private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}

扩容机制

//grow()方法是ArrayList扩容最终调用的代码
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
//旧容量向右移1位,效果等同 oldCapacity*0.5
//新的容量是旧容量的1.5倍
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);
}

总结

构造一个空的,不指定容量 ArrayList list = new ArrayList()的list时

当第一次调用add()方法向集合中添加元素时,才会扩容到10。

jdk1.6中ArrayList的扩容机制

  • jdk1.6中是扩容成原来的1.5倍+1,代码: int newCapacity = (oldCapacity * 3)/2 + 1
  • jdk1.7和jdk1.8都是扩容成原来的1.5倍

ArrayList扩容后是原来的数组还是新的数组

ArrayList扩容后是新的数组,当容量不够时,ArrayList底层通过Arrays.copyOf()方法将原来的数组拷贝到新的数组。因此,数据量多时,非常耗时。

Arrays.copyOf()内部调用System.arraycopy()方法

补充

ArrayList和Vector区别

  1. 线程安全:Vector的方法都是同步的,是线程安全的,而ArrayList不是线程安全的。由于同步会影响性能,所以,ArrayList的性能比Vector更好一些。
  2. 扩容机制:ArrayList每次扩容是其大小的1.5倍,而Vector是其大小的2倍。

ArrayList和LinkedList区别

ArrayList和LinkedList都是实现List接口的容器类

  1. 底层数据结构:ArrayList是基于动态数组的数据结构,而LinkedList是基于双向链表的数据结构。
  2. 随机访问效率:对于随机访问get和set,ArrayList要优于LinkedList,因为LinkedList要移动指针。
  3. 空间花费:ArrayList的空间浪费主要体现在list列表的结尾会预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗比ArrayList更多的空间(因为要存放直接后继和直接前驱以及数据)。
  4. 是否线程安全: ArrayList 和 LinkedList 都是不同步的,即不保证线程安全。

参考

ArrayList和LinkedList异同

Java集合--LinkedList源码分析

https://blog.51cto.com/sihai/2073367

ArrayList分析的更多相关文章

  1. ArrayList分析1-循环、扩容、版本

    ArrayList分析1-循环.扩容.版本 转载请注明出处 https://www.cnblogs.com/funnyzpc/p/16407733.html 前段时间抽空看了下ArrayList的源码 ...

  2. ArrayList分析2 :Itr、ListIterator以及SubList中的坑

    ArrayList分析2 : Itr.ListIterator以及SubList中的坑 转载请注明出处:https://www.cnblogs.com/funnyzpc/p/16409137.html ...

  3. Java集合源码学习(二)ArrayList分析

    >>关于ArrayList ArrayList直接继承AbstractList,实现了List. RandomAccess.Cloneable.Serializable接口,为什么叫&qu ...

  4. Java源码之ArrayList分析

    一.ArrayList简介 ArrayList底层的数据结构是数组,数组元素类型为Object类型,即可以存放所有类型数据. 与Java中的数组相比,它的容量能动态增长.当创建一个数组的时候,就必须确 ...

  5. 集合ArrayList分析

    目录 ArrayList 描述 重要的对象 遍历使用 与Collection关系 ArrayList属性 扩展:什么是序列化 transient关键字解析 ArrayList构造方法 无参构造 int ...

  6. JDK源码分析(一)——ArrayList

    目录 ArrayList分析 ArrayList继承结构 ArrayList字段属性 ArrayList构造函数 重要方法 ArrayList Iterator迭代器 总结 ArrayList分析   ...

  7. ArrayList继承关系分析

    目录 继承关系 Iterable Collection List AbstractCollection AbstractList RandomAccess Serializable Cloneable ...

  8. ArrayList去除重复元素(包括字符串和自定义对象)

    1.去除重复字符串 package com.online.msym; import java.util.ArrayList; import java.util.Iterator; @SuppressW ...

  9. Java集合干货——LinkedList源码分析

    前言 在上篇文章中我们对ArrayList对了详细的分析,今天我们来说一说LinkedList.他们之间有什么区别呢?最大的区别就是底层数据结构的实现不一样,ArrayList是数组实现的(具体看上一 ...

随机推荐

  1. Efficient algorithms for polyploid haplotype phasing 多倍体单体型分型的有效算法

    背景:单倍型的推断,或沿着相同染色体的等位基因序列,是遗传学中的基本问题,并且是许多分析的关键组分,包括混合物图谱,通过下降和插补识别身份区域. 基于测序读数的单倍型定相引起了很多关注. 已经广泛研究 ...

  2. asp.net网站全局控制文件内注册事件

    在管理ASP.NET网站的时候,有时会对网站整体做出控制,这时把这些代码写在global.asax内可以做到全局控制. 未添加任何代码的global.asax文件如下: <script runa ...

  3. 修改RocketMQ的NameServer端口

    ---问题--- 有同事提出各个问题:如何修改RocketMQ的NameServer端口号?(默认:9876) ---结论--- 调查并验证之后,结论及过程如下: 验证版本:rocketmq-all- ...

  4. Android内核的编译与测试

    1.下载Android内核 source.android.com/source->Downloading and Building Building Kernels 大概要花2个小时,其源码在培 ...

  5. 基于etcd插件的CoreDNS动态域名添加

    前提条件:已经有一个可用的etcd环境. 一.CoreDNS简介 CoreDNS是一个DNS服务器,和Caddy Server具有相同的模型:它链接插件.CoreDNS是云本土计算基金会启动阶段项目. ...

  6. 转 Spring AOP @Before @Around @After 等 advice 的执行顺序

    转自:http://blog.csdn.net/rainbow702/article/details/52185827 情况一: 一个方法只被一个Aspect类拦截 正常情况:  异常情况:  情况二 ...

  7. python二叉树染色-有严重BUG

    #coding:utf-8 ''' 二叉树涂黑 输入: 5 2 1 -1 4 2 -1 5 4 -1 3 1 1 2 输出: 3 第二题是:斗地主 ''' import sys b=list() cl ...

  8. 用Word2007写CSDN博客

    目前大部分的博客作者在用Word写博客这件事情上都会遇到以下3个痛点: 1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.使用Word写 ...

  9. java并发编程实战:第十三章----显示锁

    一.Lock与ReentrantLock Lock接口中定义了一种无条件.可轮询的.定时的以及可中断的锁获取操作,所有加锁和解锁的方法都是显式的. 1 public interfece Lock 2 ...

  10. 微服务中的健康监测以及其在ASP.NET Core服务中实现运行状况检查

    1 .什么是健康检查? 健康检查几乎就是名称暗示的.它是一种检查您的应用程序是否健康的方法.随着越来越多的应用程序转向微服务式架构,健康检查变得尤其重要(Health Check).虽然微服务架构有很 ...