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. Caffe 议事(二):从零开始搭建 ResNet 之 网络的搭建(上)

    3.搭建网络: 搭建网络之前,要确保之前编译 caffe 时已经 make pycaffe 了. 步骤1:导入 Caffe 我们首先在 ResNet 文件夹中建立一个 mydemo.py 的文件,本参 ...

  2. java集成支付宝移动快捷支付时报错java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence

    出错原因是代码中的私钥设置错误,不是填原始的私钥,而是转换为PKCS8格式的私钥(Java格式的) ,改成后就会报创建交易异常了

  3. IndexedDB:浏览器里内置的数据库(转)

    出处;http://www.webhek.com/indexeddb/ IndexedDB是HTML5规范里新出现的浏览器里内置的数据库.对于在浏览器里存储数据,你可以使用cookies或local ...

  4. UVa 10118 Free Candies (记忆化搜索+哈希)

    题意:有4堆糖果,每堆有n(最多40)个,有一个篮子,最多装5个糖果,我们每次只能从某一堆糖果里拿出一个糖果,如果篮子里有两个相同的糖果, 那么就可以把这两个(一对)糖果放进自己的口袋里,问最多能拿走 ...

  5. 布局分析002:入门级的CSS导航弹出菜单

    这种弹出菜单非常有意思,也有记录的意义,甚至可以说,掌握了这种弹出菜单,基本上CSS掌握的差不多. 主要涉及下面三个重要知识: CSS的继承性质. relative absolute定位. 子选择符& ...

  6. Multi-Sensor, Multi- Network Positioning

    Ruizhi Chen, Heidi Kuusniemi, Yuwei Chen, Ling Pei, Wei Chen, Jingbin Liu, Helena Leppäkoski, Jarmo ...

  7. 基于智能手机的3D地图导航

    https://www.gpsworld.com/resources/archives/ Going 3D Personal Nav and LBS To enrich user experience ...

  8. CodeForces - 468A ——(思维题)

    Little X used to play a card game called "24 Game", but recently he has found it too easy. ...

  9. kali下搭建WiFi钓鱼热点

    在linux下建立无线热点并不像在windows下开启网络共享或者使用无线网卡驱动设置AP模式即可. linux下的无线共享要用到两个软件:hostapd(创建无线热点).dnsmasq(dns服务和 ...

  10. 基于Quartz.net的远程任务管理系统 三

    在上一篇中,已经把服务端都做好了.那接下来就是Web的管理端了,因为很多时候服务器是有专门的运维来管理的,我们没有权限去操作,所以有个可以管理Job的工具还是很有必要的. Web管理端,我选择现在很成 ...