前言:以前也看过一些JDK源码,不过没有留下痕迹,经久年月就淡忘了,如今的时机也差很少了,想再看一次,而且记录下来本身的感想,因而从本身使用最多最熟悉的地方开始!而且看的过程当中,我但愿本身思考一下以下的问题:数组
1:若是让我设计,我怎么玩?数据结构
2:原做者为何这样设计?app
3:它的底层实现是什么玩意?有什么特色?dom
4:平时使用的时候,须要注意些什么东西?函数
5:原设计有什么特别好玩的点?性能
注:玩的是JDK1.7版本ui
一:先上类的继承结构图this
细细看上图,其实就能透露出一些关键的信息,好比:spa
1:实现Serializable接口,表示ArrayList是可序列化的设计
2:实现RandomAccess接口,表示ArrayList是可快速随机访问的
3:实现Cloneable接口,表示ArrayList是能够调用Object.clone方法的
4:实现Iterable接口,表示容许ArrayList使用迭代遍历的方式循环
二:再看一下他的底层实现数据结构
三:而后从源码中找点好玩的东西
从源码中能够看出ArrayList的底层数据结构是一个数组,因此,它全部的操做都是围绕着数组来玩的。
1)观察以下代码,咱们能够了解到以下信息
private 表示不能被类外操做
transient 表示经过实现Serializable接口的方式来序列化时,被其标识的类变量能够不被序列化
Object[] 表示ArrayList的通用性
/** * 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;
2)size表示数组中元素的个数,对于数组数据结构而言,数据长度至关重要
/** * The size of the ArrayList (the number of elements it contains). * * @serial */ private int size;
3)观察以下源码,咱们能够看到以下信息
ArrayList的无参构造函数,初始化的数组对象是一个空数组
ArrayList的有参构造函数,初始化的对象是根据指定的空间大小来分配数组的空间的
ArrayList是一个动态扩展的数据集合从 grow 方法中可见一二,而且当它的空间不够的时候会扩展为(大概是这样他还有一些最大最小长度的判断逻辑): 原总长度+原总长度的一半
固然ArrayList的元素的值也是有限的最大是 Integer.MAX_VALUE
/** * Shared empty array instance used for empty instances. */ private static final Object[] EMPTY_ELEMENTDATA = {};
/** * Constructs an empty list with an initial capacity of ten. */ public ArrayList() { super(); this.elementData = EMPTY_ELEMENTDATA; }
/** * Constructs an empty list with the specified initial capacity. * * @param initialCapacity the initial capacity of the list * @throws IllegalArgumentException if the specified initial capacity * is negative */ public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity]; }
/** * 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; }
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); }
/** * 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; }
/** * 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;
4)观察以下源代码,能够看到ArrayList是能够放null的,而且删除元素涉及到数据的移位复制操做是比较耗费性能的
/** * 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的源码,发现以下一些特色:
1:ArrayList的底层数据结构是数组,全部,数组这种数据结构的特色ArrayList应该也是具备的,这是他的本质
2:数组或者ArrayList这种数据结构的特色是,随机访问、循环遍历等性能好,指定位置插入或删除元素会涉及数组元素的复制,性能较差
3:ArrayList的底层数据是Object[],因此,具备很好的通用性,null也是能够存入ArrayList中的
4:ArrayList在添加元素的时候,首先会进行容量检测,若是不够会进行动态扩容
5:ArrayList使用的很是之多,使用起来也很是简单,不过看源码并不复杂,可是有些东西若是彻底弄清楚也非易事,下面我会补充一些内容以供扫除阅读源码产生的一些障碍