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. Linux下删除文件系统空间不释放的问题

    删除了Linux下的一个文件,但是系统空间并没有被释放. 如下:/home/hadmin/data/hadoop 使用了1.3T的空间,但是实际只使用了600多G 原因是我删除了一个600多G的文件, ...

  2. 手机端获取用户详细地理位置(高德地图API)

    项目开发需要获取用户详细的地理位置信息,使用了高德地图API接口 1,注册高德地图开发者账号获取开发者Key 2,页面调用 <script type="text/javascript& ...

  3. cxf的一些使用说明

    /** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agree ...

  4. 安装一个Redis

    1. 官网 http://redis.io/ 2.下载 官方不提供windows版本,但https://github.com/MSOpenTech/redis 可以从这里获取64位. 3.

  5. MFC DestroyWindow[转]

    考虑单窗口情况: 假设自己通过new创建了一个窗口对象pWnd,然后pWnd->Create.则销毁窗口的调用次序: 1. 手工调用pWnd->DestroyWindow(): 2. De ...

  6. UVA 11997 K Smallest Sums 优先队列 多路合并

    vjudge 上题目链接:UVA 11997 题意很简单,就是从 k 个数组(每个数组均包含 k 个正整数)中各取出一个整数相加(所以可以得到 kk 个结果),输出前 k 小的和. 这时训练指南上的一 ...

  7. Python学习-5.Python的变量与数据类型及字符串的分割与连接

    在Python中,变量类型是固定的,一旦声明就不能修改其类型(在Python里感觉不应该用声明,而应该用使用) 正确: var = 1 print(var) var = 2 print(var) 依次 ...

  8. .Net Core IFormFile 始终为空的问题

    之前获取上传文件都是使用Request.Form.Files获取,直到这次改成定义形参 IFormFile时才遇到这个问题. // POST api/values [HttpPost] public ...

  9. Hibernate继承映射(@Inheritance)

    继承映射在 Annotation 中使用 @Inheritance 注解,并且需要使用 strategy 属性指定继承策略,继承策略有 SINGLE_TABLE.TABLE_PER_CLASS 和 J ...

  10. HBase原理–所有Region切分的细节都在这里了

    本文由  网易云发布.   作者:范欣欣(本篇文章仅限内部分享,如需转载,请联系网易获取授权.)   Region自动切分是HBase能够拥有良好扩张性的最重要因素之一,也必然是所有分布式系统追求无限 ...