源码解析之--ArrayList
来源:互联网 发布:东莞房地产成交数据 编辑:程序博客网 时间:2024/05/22 00:25
ArrayList应该是Java日常开发中使用频率最高的集合类型之一(还有HashMap),虽然我们经常使用它,但大多数人可能都不太清楚它的实现原理和运行机制
从这篇文章中我们能学到什么:
1. ArrayList的内部定义(包括数据结构,实现接口)
2. ArrayList的最小最大容量
3. ArrayList的扩容原理
4. ArrayList的序列化方式
下面我们一起从ArrayList的源代码层面去解析吧
ArrayList内部实现
类的定义
// AbstractList中声明了List该有的一些方法,同时实现了迭代器// ArrayList具有随机访问、克隆以及序列化的能力public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable,java.io.Serializable
数据结构
// ArrayList内部实现就是这个数组,其length就是ArrayList的capacity// transient关键字意味着elementData将不会序列化,那么ArrayList又将如何序列化?transient Object[] elementData;
new ArrayList<>()方法
// 这里说明new ArrayList<>()时,ArrayList是空的,capacity为0public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}
ArrayList的容量
// ArrayList的默认的容量大小是10private static final int DEFAULT_CAPACITY = 10;// 空listprivate static final Object[] EMPTY_ELEMENTDATA = {};// 创建ArrayList实例时,如果未提供capacity,那ArrayList内部将会是这个数组,其capacity是0,然后在add第一个元素的时候进行扩容。private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};// ArrayList的最大容量是Integer.MAX_VALUE - 8,减8的原因是因为一些虚拟机在数组中有预留位保存头部信息/** * 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;
ArrayList的扩容校验
add方法
// add首先会就行容量校验public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true;}
ensureCapacityInternal方法
// 当elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA时,会将list的capacity设置为Math.max(DEFAULT_CAPACITY, minCapacity),所以capacity至少会是10private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity) } ensureExplicitCapacity(minCapacity);}
ArrayList扩容
// 至少会扩容 1/2 oldCapacity(向下取整)// 如果newCapacity小于最少需要的容量minCapacity,那newCapacity=minCapacityprivate 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);}// 取MAX_ARRAY_SIZE或者抛出OutOfMemoryError异常private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;}// 该方法中调用了grow方法,即当前需要的容量要比当前ArrayList的capacity大时进行扩容private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity);}
ArrayList序列化
为什么ArrayList会采用这两个方法来完成序列化与反序列化,见Java集合序列化
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 ensureCapacityInternal(size); Object[] a = elementData; // Read in all elements in the proper order. for (int i=0; i<size; i++) { a[i] = s.readObject(); } } }
总结
回答一下上面的几点问题:
1、ArrayList内部如何实现?适合什么样的操作场景?
数组实现,适合查询频繁的场景,不适合非尾部的增删操作;实现了AbstractList,迭代器,还具有具有随机访问、克隆以及序列化的能力
2、new ArrayList<>()方法调用后所提供的ArrayList容量是多大?
答案是0,从上面可以看出是调用了add方法后才有的容量,且至少为10
3、ArrayList什么时候扩容?如何扩容?扩多大?
当前需要的容量要比当前ArrayList的capacity大时进行扩容;扩容的操作是重新分配数组;至少会扩容 1/2 oldCapacity(向下取整),如果newCapacity小于最少需要的容量minCapacity,那将扩大至最少需要容量。
4、ArrayList如何序列化?
通过readObject和writeObject,详见集合序列化
5、ArrayList最大容量是多大?
Integer.MAX_VALUE - 8,部分虚拟机在数组中预留了8位存储头部信息。
6、如果要看Vector和ArrayList,LinkedList的区别
请移步http://blog.csdn.net/qq_28260521/article/details/78707400
如果您觉得我的文章帮到了您,请下方评论个1,您的支持是我最大的动力
阅读全文
0 0
- 源码解析之--ArrayList
- JDK源码解析之ArrayList
- Java 源码解析之 ArrayList
- java之ArrayList源码解析
- JDK之ArrayList源码解析
- JDK源码解析之ArrayList
- 【源码解析】JDK源码之ArrayList
- List源码解析之ArrayList源码分析
- Java Collection Framework 之 ArrayList 源码解析
- Java集合之 ArrayList源码解析
- JDK源码解析之ArrayList和LinkedList
- Java集合之ArrayList源码解析
- ArrayList 源码解析
- ArrayList源码解析
- android源码解析 -- ArrayList
- ArrayList源码解析
- ArrayList源码解析
- ArrayList源码解析
- Postgresql常见操作指令
- hammer.js操作svg使达到平移,缩放
- vue 过滤器基本用法
- Servlet介绍(一)
- 逆向微信------给微信加上控件
- 源码解析之--ArrayList
- Anaconda Python OpenCV(OpenCV contrib)导入cv2出现找不到dll问题
- 最长公共子序列
- MyEclipse中的快捷键
- 浅析ArrayList和LinkedList
- Win2008 Server R2 服务器拒绝共享访问
- 复制字符串
- vim 快捷键
- 移动端touchstart、touchend触摸事件的简单使用