源码分析--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 ...
随机推荐
- Cobaltstrike系列教程(三)-beacon详解
0x000--前文 Cobaltstrike系列教程(一)-简介与安装 Cobaltstrike系列教程(二)-Listner与Payload生成 heatlevel 0x001-Beacon详解 1 ...
- 11:如何解决Maven的Jar版本冲突问题
右键 Exclude,排除冲突包
- spring boot 1.视图解析器,2.开启静态资源访问
1.spring boot 视图解析器 #视图解析器 #前缀spring.mvc.view.prefix=/pages/ #后缀..jsp.dospring.mvc.view.suffix=.jsp ...
- php怎么启动exe文件
PHP作为一种服务器端的脚本语言,象编写简单,或者是复杂的动态网页这样的任务,它完全能够胜任.但事情不总是如此,有时为了实现某个功能,必须借助于操作系统的外部程序(或者称之为命令),这样可以做到事半功 ...
- zabbix4.0 percona插件实现监控mysql
percona是一款能够详细监控zabbix MySQL的插件 官方下载percona插件 wget https://www.percona.com/downloads/percona-monitor ...
- Android解析编译之后的所有文件(so,dex,xml,arsc)格式
我们在之前一篇一篇介绍了如何解析Android中编译之后的所有文件格式,所有的工作都完成了,这里我们就来做个总结,我们为什么要做这些工作: 第一篇:解析so文件格式 点击进入 这里我们解析so文件,主 ...
- postman 简单使用教程
Postman 安装 Postman 接口测试(Collection) Postman 接口测试(测试用例)Postman 接口测试(变量与参数化)Postman 接口测试(非 UI 运行模式 ...
- JS实现多Div模块拖拽功能
空闲时间,同事让帮忙整个JS拖拽div模块功能.于是便在网上搜索,总结如下一个可实现多div模块拖拽的功能.一下是整体的HTML代码, 里边可以控制到 拖拽开始(onStart),拖拽时候(onMov ...
- codeforces 380A Sereja and Prefixes (递归)
题目: A. Sereja and Prefixes time limit per test 1 second memory limit per test 256 megabytes input st ...
- android7.0后对于detected problems with app native libraries提示框显示
log信息: 03-27 09:08:25.887 397 400 W linker : /data/app/com.guagua.qiqi-1/lib/arm/libMedia.so ha ...