Java 的 ArrayList 的底层数据结构
1. 数据结构--ArrayList源码摘要
ublic class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable {private static final long serialVersionUID = 8683452581122892189L;/*** Default initial capacity.*/private static final int DEFAULT_CAPACITY = 10;/*** Shared empty array instance used for empty instances.*/private static final Object[] EMPTY_ELEMENTDATA = {};/*** 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 == EMPTY_ELEMENTDATA will be expanded to* DEFAULT_CAPACITY when the first element is added.*/private transient Object[] elementData;/*** The size of the ArrayList (the number of elements it contains).** @serial*/private int size; }
ArrayList 的底层最重要的两个属性:Object 数组和 size 属性。
2. ArrayList 的底层数组的调整
add方法--ArrayList源码摘要
/*** 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); // Increments modCount!!elementData[size++] = e;return true;}
grow方法--ArrayList源码摘要
/**
* Increases the capacity of this <tt>ArrayList</tt> instance, if
* necessary, to ensure that it can hold at least the number of elements
* specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
public void ensureCapacity(int minCapacity) {
int minExpand = (elementData != EMPTY_ELEMENTDATA)
// any size if real element table
? 0
// larger than default for empty table. It's already supposed to be
// at default size.
: DEFAULT_CAPACITY;
if (minCapacity > minExpand) {
ensureExplicitCapacity(minCapacity);
}
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
/**
* The maximum size of array to allocate.
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
* 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);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
2点结论:
a. ArrayList 是通过将底层 Object 数组复制的方式(System.arraycopy方法)来处理数组的增长;
b. 当ArrayList 的容量不足时,其扩充容量的方式:先将容量扩充至当前容量的1.5倍,若还不够,则将容量扩充至当前需要的数量(grow方法)。
remove 方法--ArrayList源码摘要
/*** Removes the element at the specified position in this list.* Shifts any subsequent elements to the left (subtracts one from their* indices).** @param index the index of the element to be removed* @return the element that was removed from the list* @throws IndexOutOfBoundsException {@inheritDoc}*/public E remove(int index) {rangeCheck(index);modCount++;E oldValue = elementData(index);int numMoved = size - index - 1;if (numMoved > 0)System.arraycopy(elementData, index+1, elementData, index,numMoved);elementData[--size] = null; // clear to let GC do its workreturn oldValue;}
/**
* Removes the first occurrence of the specified element from this list,
* if it is present. If the list does not contain the element, it is
* unchanged. More formally, removes the element with the lowest index
* <tt>i</tt> such that
* <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>
* (if such an element exists). Returns <tt>true</tt> if this list
* contained the specified element (or equivalently, if this list
* changed as a result of the call).
*
* @param o element to be removed from this list, if present
* @return <tt>true</tt> if this list contained the specified element
*/
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
/*
* Private remove method that skips bounds checking and does not
* return the value removed.
*/
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
}
这也就解释了 ArrayList 的特点:增加、删除和移动元素的效率低(数组复制过程消耗资源较多); 而查找元素和更新元素的效率高。
3. ArrayList与Vector的区别
1) vector 是线程同步的,所以它也是线程安全的,而arraylist 是线程异步的,是不安全的。如果不考虑到线程的安全因素,一般用 arraylist效率比较高。
2)如果集合中的元素的数目大于目前集合数组的长度时,vector 增长率为目前数组长度的100%, 而arraylist 增长率为目前数组长度的50% .如果在集合中使用数据量比较大的数据,用vector有一定的优势。
3)如果查找一个指定位置的数据,vector和arraylist使用的时间是相同的,都是O(1) ,这个时候使用vector和arraylist都可以。
而如果移动一个指定位置的数据花费的时间为O(n-i)n为总长度,这个时候就应该考虑到使用linklist ,因为它移动一个指定位置的数据所花费的时间为0(1),而查询一个指定位置的数据时花费的时间为0(i)。
转载于:https://www.cnblogs.com/dassmeta/p/5334960.html
Java 的 ArrayList 的底层数据结构相关推荐
- 【Java基础】HashMap底层数据结构及其原理
1.简单了解一下HashMap HashMap 就是以 Key-Value 键值对的方式进行数据存储的一种数据结构,它在 JDK 1.7 和 JDK 1.8 中底层数据结构是有些不一样的.简单来说,J ...
- java中什么是底层数据结构_JavaScript 对象的底层数据结构是什么
这也是个老生常谈的问题,最近得空也开始总结下这方面的知识点.学过java的同学,都知道java把内存分为两种形式,一种是栈内存,另一种是堆内存.java的基本类型(int,short,long,byt ...
- Java集合- HashMap 的底层数据结构实现原理
一.HashMap 的数据结构 JDK1.8 之前 JDK1.8 之前 HashMap 底层是 数组和链表 结合在一起使用也就是 链表散列. HashMap 通过 key 的 hashCode 经过扰 ...
- Java集合—ArrayList底层原理
原文作者:0 errors 0 warnings 原文地址:用大白话告诉你ArrayList的底层原理 目录 一.数据结构 二.线程安全性 三.继承关系 四.构造方法 五.add()方法 六.扩容机制 ...
- ArrayList的底层实现原理
ArrayList源码分析 1.java.util.ArrayList<E> : List 接口的大小可变数组的实现类 ArrayList 内部基于 数组 存储 各个元素. 所谓大小可变数 ...
- 深入Java集合ArrayList的源码解析
现在由大恶人付有杰来从增删改查几个角度轻度解析ArrayList的源码 首先ArrayList的底层数据结构非常简单,就是一个数组. 从源码第115行我们可以得出信息,他的默认数组长度是10. /** ...
- ArrayList 集合底层实现原理解析
文章目录 1. ArrayList 集合底层数据结构 1. ArrayList 集合介绍 2. 数组结构介绍 2. ArrayList 继承关系 2.1 Serializable 标记性接口 2.2 ...
- 【java版数据结构】看完数据结构的顺序结构后,紧接着去实现ArrayList的底层(150行代码,数组扩容,增删改查,但未实现迭代器)
实现效果: 需求分析: 可以看到ArrayList容器有很多功能,在指定位置添加元素,在容器末尾添加元素,获取指定位置的元素,获取容器的大小,清空容器的元素,判断容器是否是空的,删除指定位置的元素,删 ...
- Java基础(19)数据结构概述、ArrayList集合、Vector集合、LinkedList集合、集合框架练习
1. 数据结构概述 1. 数据结构的概述:数据结构就是数据存储的方式 2. 常见数据结构:栈,队列,数组,链表,二叉树,哈希表 3. 栈和队列 (1)栈:先进后出,后进先出 (2)队列:先进先出,后进 ...
最新文章
- 如何“快”、“准”、“狠”成为优秀算法工程师
- 黄聪:C# MP3操作类,能播放指定的mp3文件,或播放嵌入的资源中的Mp3文件
- 对于Array的引用
- QtQuick 中的 qml 与 Qt 的 C++
- springboot jwt token前后端分离_「转」七个开源的 Spring Boot 前后端分离项目,建议收藏加转载...
- MATLAB调用C/C++函数的方法
- I/O设备的编址方式(统一编址,独立编址)
- activeMQ入门安装
- C++容器,迭代器,容器的适配器
- 跨过虚拟化技术浪潮,这家企业快步入局云数据管理​
- Android viewpager 嵌套 viewpager滑动 点击事件冲突解决方案
- 有序表的索引顺序结构查找次数分析
- 敏捷无敌之Gitlab CI实战
- 步进电机代替舵机方案
- QT之如何添加现有文件
- 苹果手机上网很慢_手机4G信号满格,上网速度却很慢?原来都是它们在“搞鬼”...
- MySQL安装QT连接MySQL学习记录
- 关于vue-cli3的浏览器兼容性
- 小甲鱼零基础学习python_19 【pickle -- 腌制一缸泡菜】
- android第三方上传文件,安卓和苹果终于打通!互传文件无需借助第三方,一碰就能传...
热门文章
- h.264并行解码算法分析
- 前端大牛or架构师应该具备这些
- 安装linux环境及相关包方法
- linux下使用source /etc/profile保存配置后,新的环境变量只能在一个终端里面有效...
- 当世界从移动优先变为AI优先,未来企业竞争将赢在“维度”
- 搭建一个项目的准备工作
- strcat与strncat的C/C++实现
- 一步一步重写 CodeIgniter 框架 (2) —— 实现简单的路由功能
- Ogre:ManualObject
- 页面间传值的新思路--PreviousPage