源码分析--ArrayList(JDK1.8)
ArrayList是开发常用的有序集合,底层为动态数组实现。可以插入null,并允许重复。
下面是源码中一些比较重要属性:
1、ArrayList默认大小10。
/**
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10;
2、elementData就是真正存放数据的数组。elementData[]本身是动态的,并不是数组的全部空间都会使用,所以加上transient关键词进行修饰,防止自动序列化。
transient Object[] elementData; // non-private to simplify nested class access
3、ArrayList的实际大小。每次进行add或者remove后,都会进行跟踪修订。
/**
* The size of the ArrayList (the number of elements it contains).
*
* @serial
*/
private int size;
下面分析主要方法:
1、add()方法有两个实现,一种是直接添加,一种是指定index添加。
直接添加代码如下:
/**
* 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;
}
- 扩容判断
- 元素插入elementData[]尾部,size加1
指定index添加方式:
public void add(int index, E element) {
rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
- 根据当前size,判断指定索引是否合理
- 扩容判断
- 将原数组中从index往后的全部元素copy到index+1之后的位置。也就是把后续元素的索引全部+1
- 需插入的元素放入指定index
- size加1
add()方法中,数组扩容调用的最终方法如下:
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);
}
代码中看得出,ArrayList会在原先容量的基础上,扩容为原来的1.5倍(oldCapacity + (oldCapacity >> 1)),最大容量为Integer.MAX_VALUE。elementData也就是一个数组复制的过程了。所以在平常的开发中,实例化ArrayList时,可以尽量指定容量大小,减少扩容带来的数组复制开销。
2、remove()方法和add()类似,这里就只简单看下:
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;
}
也就是拿到删除元素的index后,用数组复制的方式进行元素的覆盖。最后一个elementData数组的元素就是成了垃圾数据,让GC进行回收。size减1。
3、序列化
/**
* Save the state of the <tt>ArrayList</tt> instance to a stream (that
* is, serialize it).
*
* @serialData The length of the array backing the <tt>ArrayList</tt>
* instance is emitted (int), followed by all of its elements
* (each an <tt>Object</tt>) in the proper order.
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject(); // Write out size as capacity for behavioural compatibility with clone()
s.writeInt(size); // Write out all elements in the proper order.
for (int i=0; i<size; i++) {
s.writeObject(elementData[i]);
} if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
} /**
* Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,
* deserialize it).
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
elementData = EMPTY_ELEMENTDATA; // Read in size, and any hidden stuff
s.defaultReadObject(); // Read in capacity
s.readInt(); // ignored if (size > 0) {
// be like clone(), allocate array based upon size not capacity
int capacity = calculateCapacity(elementData, size);
SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity);
ensureCapacityInternal(size); Object[] a = elementData;
// Read in all elements in the proper order.
for (int i=0; i<size; i++) {
a[i] = s.readObject();
}
}
}
ArrayList是用动态数组elementData进行数据存储的,所以本身自定义了序列化与反序列化方法。当对象中自定义了 writeObject 和 readObject 方法时,JVM 会调用这两个自定义方法来实现序列化与反序列化。ArrayList只序列化elementData里面的数据。
源码分析--ArrayList(JDK1.8)的更多相关文章
- HashMap 源码分析 基于jdk1.8分析
HashMap 源码分析 基于jdk1.8分析 1:数据结构: transient Node<K,V>[] table; //这里维护了一个 Node的数组结构: 下面看看Node的数 ...
- 【JDK】JDK源码分析-ArrayList
概述 ArrayList 是 List 接口的一个实现类,也是 Java 中最常用的容器实现类之一,可以把它理解为「可变数组」. 我们知道,Java 中的数组初始化时需要指定长度,而且指定后不能改变. ...
- LinkedList源码分析(jdk1.8)
LinkedList概述 LinkedList 是 Java 集合框架中一个重要的实现,我们先简述一下LinkedList的一些特点: LinkedList底层采用的双向链表结构: LinkedL ...
- [源码分析]ArrayList和LinkedList如何实现的?我看你还有机会!
文章已经收录在 Github.com/niumoo/JavaNotes ,更有 Java 程序员所需要掌握的核心知识,欢迎Star和指教. 欢迎关注我的公众号,文章每周更新. 前言 说真的,在 Jav ...
- HashMap实现原理及源码分析(JDK1.7)
转载:https://www.cnblogs.com/chengxiao/p/6059914.html 哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技 ...
- CopyOnWriteArrayList 源码分析 基于jdk1.8
CopyOnWriteArrayList 源码分析: 1:成员属性: final transient ReentrantLock lock = new ReentrantLock(); //内部是 ...
- ArrayList 源码分析(JDK1.8)
ArrayList简介 ArrayList 是一个数组队列,相当于 动态数组.与Java中的数组相比,它的容量能动态增长.它继承于AbstractList,实现了List, RandomAccess ...
- ArrayList源码分析(JDK1.8)
概述 ArrayList底层是基于数组实现的,并且支持动态扩容的动态数组(变长的集合类).ArrayList允许空值和重复的元素,当向ArrayList中添加元素数量大于其底层数组容量时,会通过扩容机 ...
- JDK源码分析 – ArrayList
ArrayList类的申明 ArrayList是一个支持泛型的,底层通过数组实现的一个可以存任意类型的数据结构,源码中的定义如下: public class ArrayList<E> ex ...
随机推荐
- 前端每日实战:45# 视频演示如何用纯 CSS 创作一个菱形 loader 动画
效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/eKzjqK 可交互视频教程 此视频 ...
- web--响应式导航菜单
响应式导航菜单 代码如下 HTML代码: <!DOCTYPE html> <html lang="en"> <head> <meta ch ...
- pandas学习(一)
pandas.DataFrame.sort_index 用法 sort_index(axis=0, level=None, ascending=True, inplace=False, kind='q ...
- 用于DataLoader的pytorch数据集
暂时介绍 image-mask型数据集, 以人手分割数据集 EGTEA Gaze+ 为例. 准备数据文件夹 需要将Image和Mask分开存放, 对应文件的文件名必须保持一致. 提醒: Mask 图像 ...
- Test 6.29 T2 染色
问题描述 于是 CJK 轻轻松松就切了第一题."好,那么来看看第二题吧." JesseLiu 大手一挥,CJK 眼前立刻出现了一棵有 n 个节点的树."现在,你将要为这颗 ...
- 【leetcode】1027. Longest Arithmetic Sequence
题目如下: Given an array A of integers, return the length of the longest arithmetic subsequence in A. Re ...
- 1349 - View's SELECT contains a subquery in the FROM clause
mysql创建视图 报错1349 - View's SELECT contains a subquery in the FROM clause:: 原因创建视图的sql语句中有不支持子查询, 所以需要 ...
- git怎样删除未监视的文件untracked files ?
git怎样删除未监视的文件untracked files 需要添加到.gitignore文件 # 删除 untracked files git clean -f # 连 untracked 的目录也一 ...
- POJ 1511 Invitation Cards ( 双向单源最短路 || 最小来回花费 )
题意 : 给出 P 个顶点以及 Q 条有向边,求第一个点到其他各点距离之和+其他各点到第一个点的距离之和的最小值 分析 : 不难看出 min( 第一个点到其他各点距离之和+其他各点到第一个点的距离之和 ...
- 流氓软件修改IE主页的解决方法
运行regedit HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Main 修改以下url Default_Page_URL Firs ...