当前位置:网站首页>ArrayList源码解析
ArrayList源码解析
2022-06-24 18:34:00 【小码code】
在平时Java,存储数据需要用到列表,而大多时候都能用到ArrayList,比如Mybatis查询数据列表,返回列表都是ArrayList,很多数据的存放也用到了ArrayList。
jdk 版本: 1.8
ArrayList 是基于大小可变的数组实现,并允许添加null值, 根据下标就能数据查询快。数组一旦初始化就确定好了大小,如果需要添加数据,就需要做数据的复制,这些操作比较耗时。
前言
ArrayList查询数据直接根据下标获取数据,而数据的添加和删除涉及数组的复制,主要用到了两个方法:
System.arraycopyArrays.copyOf
System.arraycopy
arraycopy(Object src, int srcPos,Object dest, int destPos,int length) 将数组的src,从起始位置srcPos到最后的数据。复制给dest数组,起始位置为destPos,长度为length
将数组 src 从srcPos起始长度为length的数据赋值给数组dest的起始为destPos
Arrays.copyOf
Arrays.copyOf也是调用System.arraycopy方法:
public static int[] copyOf(int[] original, int newLength) {
int[] copy = new int[newLength];
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
首先创建一个新的数组copy,将original数组全部复制给copy数组。
主要的实例变量:
// 底层数组
transient Object[] elementData;
// 数组个数大小
private int size;
// 默认空数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
ArrayList是基于数组的一个实现,elementData就是底层的数组。size是记录数组的个数。
新建一个ArrayList实例:
List<Integer> list = new ArrayList<>();
首先调用无参构造方法,直接赋值一个空数组DEFAULTCAPACITY_EMPTY_ELEMENTDATA。
添加数据
添加数据有两个方法:
add(E e) 直接添加在数组尾部。 add(int index, E element) 根据下标添加数据。
add(E e)
在列表尾部添加数据:
/**
* Appends the specified element to the end of this list.
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
ensureCapacityInternal 判断添加数据后的容量是否足够,如果不够,做扩容操作。
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
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);
}
ensureCapacityInternal先调用calculateCapacity,然后再调用ensureExplicitCapacity。
calculateCapacity 当前数组为null时,就返回10 和 minCapacity 的最大值,否则返回minCapacity。这个方法就是返回数组的大小。
ensureExplicitCapacity 判断 minCapacity 大于 elementData.length 做扩容处理,这里重点将 grow 方法:
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
// 新长度是原来长度的 1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
// 新长度比需要长度更小,赋值给新长度
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 拷贝数组到新的长度数组
elementData = Arrays.copyOf(elementData, newCapacity);
}
group 主要做了两件事:
长度扩大到原来的 1.5倍 拷贝数组到新长度的数组
做完判断是否要做扩容之后,直接在size位置上赋值要添加的元素,然后size再自增。
elementData[size++] = e;
add 方法主要有两个步骤:
判断是否要进行扩容,新添加数据数组长度大于现有的数组长度,进行 1.5的扩容。在数组 size下标赋值数据。
add(int index, E element)
此添加数据是在指定的下标添加数据。
public void add(int index, E element) {
// 下标是否越界
rangeCheckForAdd(index);
// 判断是否要扩容
ensureCapacityInternal(size + 1); // Increments modCount!!
// 复制i到size的数据到i+1 到size +1
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
add(int index, E element) 在index下标添加数据,
首先判断 index是否在0 ~size之间。判断是否要扩容,需要扩容,进行 1.5倍扩容。数据迁移,把 index以后的数据全部往后移动一位。赋值 index下标数据。

获取数据
获取数据只有通过数组下标获取数据 get(int index):
public E get(int index) {
//检查是否超过数组范围
rangeCheck(index);
return elementData(index);
}
@SuppressWarnings("unchecked")
E elementData(int index) {
// 通过下标获取数据
return (E) elementData[index];
}
这里获取数据就比较简单:
检查下标是否超过数组范围。 通过下标访问数据。
删除数据
remove(Object o)
删除列表中第一个匹配的元素:
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;
}
判断要删除数据是否为null:
为空,判断 elementData[index]是否为空。不为空,判断元素 equals是否匹配elementData[index]。
上面判断都为true时,调用fastRemove方法:
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
}
移动数组数据,index+1 以及之后的数据往前移动一位,最后一位size-1赋值为null。

remove(int index)
根据index下标删除数据。
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 work
return oldValue;
}
边栏推荐
- JS string method
- 360 digital released information security trends in January: 120000 fraud risks were captured and users were reminded 2.68 million times
- Is it safe to open an account online? What should I do?
- Analysis on the issue of raising the right of MSSQL in 2021 secondary vocational group network security competition in Shandong Province
- congratulate! The first dragon lizard community annual outstanding contribution award is announced. Check it now
- Different JVM
- Volcano成Spark默认batch调度器
- 时间溯源的系统设计思路
- Introduction and download tutorial of administrative division vector data
- How do programmers do we media?
猜你喜欢

The verifiable certificate of geoscience remote sensing industry

Flutter dart regular regexp matches non printing characters \cl\cj\cm\ck

JS deep understanding of functions

FROM_ GLC introduction and data download tutorial

JS pre parsing

Sr-gnn shift robot gnns: overlapping the limitations of localized graph training data

解读HarmonyOS 应用与服务生态

Sudoku (easy to understand)

Vite+web3: referenceerror: process is not defined

Architecture decryption from distributed to microservice: several common microservice architecture schemes
随机推荐
论文解读(SR-GNN)《Shift-Robust GNNs: Overcoming the Limitations of Localized Graph Training Data》
MySQL basic commands
Network security database penetration of secondary vocational group in 2022
Several ways of connecting upper computer and MES
Executing SQL statements with parameterized commands
上位机与MES对接的几种方式
Flutter dart regular regexp special characters $, () (IV)
Navigator object
An analysis of the comments on the TV series Douban by procedural apes
Solve the problem that the MapReduce program console does not have log information warn please initialize the log4j system properly
Make track map
congratulate! The first dragon lizard community annual outstanding contribution award is announced. Check it now
论文解读(SR-GNN)《Shift-Robust GNNs: Overcoming the Limitations of Localized Graph Training Data》
JS picture display and hiding cases
Graph traversal (BFS and DFS) C language pure handwriting
微服务系统设计——子服务项目构建
中电投先融期货这家公司怎么样?期货开户办理安全吗?
JDBC writes Chinese garbled code to the database
Vite+web3:报错出现ReferenceError: process is not defined
Remote sensing Forum