ArrayList类源码解析
2016-07-15 16:49
337 查看
ArrayList特点:
1.内部通过数组实现
2.删除、插入元素需要大量移动元素
3.默认存储容量是null,需要增加容量时候,默认增加的容量等于原始ArrayList的容量
4.没有实现同步方法,多线程的时候,线程不安全,效率较高
5.存储元素的顺序就说加入集合中的顺序,方便指定index访问元素
所在包
继承AbstractList抽象类
实现List、RandomAccess、Cloneable、java.io.Serializable
5个参数
三个构造器
修剪elementData,保证其内部的元素都是有效元素
elementCount 记录实际元素个数
容量大小等于元素个数
增加容量的操作
具体分为下面几步:
1.是否需要增加容量
2.增加多少容量
3.增加容量
获取ArrayList元素个数
判断是否空
是否包含元素o
元素o第一次出现的下标
元素o最后一次出现的下标
clone
ArrayList内元素复制到数组,并返回这个数组
ArrayList内元素更新数组a
获取index位置元素
不抛出异常
获取index位置元素
可抛出异常
更新index位置元素
尾部加入元素
index位置插入元素
删除index位置元素
删除元素o
具体删除操作
清空操作
元素设为null
size设为0
添加集合c元素到ArrayList中
index位置开始插入集合c的元素
删除区间内元素
index是否合法检查
差集
交集
差集交集具体实现
输出流和输入流
三个不同类型的迭代器
内部类实现Itr迭代器
只能够向后遍历
ListItr 迭代器,继承Itr,并增加了前驱遍历、更新元素的方法
获取子数组,以及其迭代器代码,和上面很类似
1.内部通过数组实现
2.删除、插入元素需要大量移动元素
3.默认存储容量是null,需要增加容量时候,默认增加的容量等于原始ArrayList的容量
4.没有实现同步方法,多线程的时候,线程不安全,效率较高
5.存储元素的顺序就说加入集合中的顺序,方便指定index访问元素
所在包
package java.util;
继承AbstractList抽象类
实现List、RandomAccess、Cloneable、java.io.Serializable
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable{ // 内部代码下面讲解 }
5个参数
private static final long serialVersionUID = 8683452581122892189L; /** * 默认容量 */ private static final int DEFAULT_CAPACITY = 10; /** * 空数组 */ private static final Object[] EMPTY_ELEMENTDATA = {}; /** * 数组存储元素 */ private transient Object[] elementData; /** * ArrayList内元素个数 */ private int size;
三个构造器
/** * initialCapacity容量大小 * * @throws initialCapacity 小于0的时候,抛出:IllegalArgumentException */ public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) // 抛出异常 throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity]; // 新建initialCapacity大小的数组 } /** * 无参构造器,容量是空 */ public ArrayList() { super(); this.elementData = EMPTY_ELEMENTDATA; } /** * 集合c中的元素加入的数组中 * @throws 集合空的时候 抛出:NullPointerException */ public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); size = elementData.length; // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) // 集合内的元素复制到element中 elementData = Arrays.copyOf(elementData, size, Object[].class); }
修剪elementData,保证其内部的元素都是有效元素
elementCount 记录实际元素个数
容量大小等于元素个数
public void trimToSize() { modCount++; if (size < elementData.length) { elementData = Arrays.copyOf(elementData, size); } }
增加容量的操作
具体分为下面几步:
1.是否需要增加容量
2.增加多少容量
3.增加容量
/** * @param minCapacity 最小容量,这个时候容量等于ArrayList内元素的大小 */ public void ensureCapacity(int minCapacity) { int minExpand = (elementData != EMPTY_ELEMENTDATA) // any size if real element table ? 0 // larger than default for empty table. It's already supposed to be // at default size. : DEFAULT_CAPACITY; if (minCapacity > minExpand) { ensureExplicitCapacity(minCapacity); } } 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); // 增加容量 } /** * 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; /** * @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; }
获取ArrayList元素个数
public int size() { return size; }
判断是否空
public boolean isEmpty() { return size == 0; }
是否包含元素o
public boolean contains(Object o) { return indexOf(o) >= 0; }
元素o第一次出现的下标
public int indexOf(Object o) { if (o == null) { for (int i = 0; i < size; i++) if (elementData[i]==null) return i; } else { for (int i = 0; i < size; i++) if (o.equals(elementData[i])) return i; } return -1; }
元素o最后一次出现的下标
public int lastIndexOf(Object o) { if (o == null) { for (int i = size-1; i >= 0; i--) if (elementData[i]==null) return i; } else { for (int i = size-1; i >= 0; i--) if (o.equals(elementData[i])) return i; } return -1; }
clone
public Object clone() { try { @SuppressWarnings("unchecked") ArrayList<E> v = (ArrayList<E>) super.clone(); v.elementData = Arrays.copyOf(elementData, size); v.modCount = 0; return v; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable throw new InternalError(); } }
ArrayList内元素复制到数组,并返回这个数组
public Object[] toArray() { return Arrays.copyOf(elementData, size); }
ArrayList内元素更新数组a
/* @throws ArrayStoreException if the runtime type of the specified array * is not a supertype of the runtime type of every element in * this list * @throws NullPointerException if the specified array is null */ @SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { if (a.length < size) // Make a new array of a's runtime type, but my contents: return (T[]) Arrays.copyOf(elementData, size, a.getClass()); System.arraycopy(elementData, 0, a, 0, size); if (a.length > size) a[size] = null; return a; }
获取index位置元素
不抛出异常
@SuppressWarnings("unchecked") E elementData(int index) { return (E) elementData[index]; }
获取index位置元素
可抛出异常
/* @throws IndexOutOfBoundsException {@inheritDoc} */ public E get(int index) { rangeCheck(index); return elementData(index); }
更新index位置元素
/* @throws IndexOutOfBoundsException {@inheritDoc} */ public E set(int index, E element) { rangeCheck(index); E oldValue = elementData(index); elementData[index] = element; return oldValue; }
尾部加入元素
public boolean add(E e) { ensureCapacityInternal(size + 1); // 是否增加容量 elementData[size++] = e; return true; }
index位置插入元素
/* @throws IndexOutOfBoundsException {@inheritDoc} */ public void add(int index, E element) { rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // 是否增加容量 System.arraycopy(elementData, index, elementData, index + 1,size - index); elementData[index] = element; size++; }
删除index位置元素
/* @throws IndexOutOfBoundsException */ public E remove(int index) { rangeCheck(index);// 检查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; }
删除元素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; }
具体删除操作
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 }
清空操作
元素设为null
size设为0
public void clear() { modCount++; // clear to let GC do its work for (int i = 0; i < size; i++) elementData[i] = null; size = 0; }
添加集合c元素到ArrayList中
/* @throws NullPointerException if the specified collection is null */ public boolean addAll(Collection<? extends E> c) { Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); // Increments modCount System.arraycopy(a, 0, elementData, size, numNew); size += numNew; return numNew != 0; }
index位置开始插入集合c的元素
/* @throws IndexOutOfBoundsException {@inheritDoc} * @throws NullPointerException if the specified collection is null */ public boolean addAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index);// 检查index是否合法 Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); // 是否需要增加容量 int numMoved = size - index;// 需要移动元素数量 if (numMoved > 0) System.arraycopy(elementData, index, elementData, index + numNew,numMoved); // 后移 System.arraycopy(a, 0, elementData, index, numNew);// 插入 size += numNew;// 更新元素数量 return numNew != 0; }
删除区间内元素
/* @throws IndexOutOfBoundsException if {@code fromIndex} or * {@code toIndex} is out of range * ({@code fromIndex < 0 || * fromIndex >= size() || * toIndex > size() || * toIndex < fromIndex}) */ protected void removeRange(int fromIndex, int toIndex) { modCount++; int numMoved = size - toIndex;// 移动元素数量 System.arraycopy(elementData, toIndex, elementData, fromIndex,numMoved); // 移动 // clear to let GC do its work int newSize = size - (toIndex-fromIndex); // 更新size for (int i = newSize; i < size; i++) { // 后面部分设null elementData[i] = null; } size = newSize; }
index是否合法检查
/** * 检查index是否合法,没有对负数进行判断,是负数的时候抛出ArrayIndexOutOfBoundsException * */ private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } /** * 添加元素时候index检查 */ private void rangeCheckForAdd(int index) { if (index > size || index < 0) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } /** * 越界输出信息 */ private String outOfBoundsMsg(int index) { return "Index: "+index+", Size: "+size; }
差集
/* @throws ClassCastException if the class of an element of this list * is incompatible with the specified collection * @throws NullPointerException if this list contains a null element and the * specified collection does not permit null elements * or if the specified collection is null * @see Collection#contains(Object) */ public boolean removeAll(Collection<?> c) { return batchRemove(c, false); }
交集
/* @throws ClassCastException if the class of an element of this list * is incompatible with the specified collection * @throws NullPointerException if this list contains a null element and the * specified collection does not permit null elements * or if the specified collection is null * @see Collection#contains(Object) */ public boolean retainAll(Collection<?> c) { return batchRemove(c, true); }
差集交集具体实现
private boolean batchRemove(Collection<?> c, boolean complement) { final Object[] elementData = this.elementData; int r = 0, w = 0; boolean modified = false; try { for (; r < size; r++) if (c.contains(elementData[r]) == complement) // true 交集,false差集 elementData[w++] = elementData[r]; } finally { // Preserve behavioral compatibility with AbstractCollection, // even if c.contains() throws. if (r != size) { System.arraycopy(elementData, r, elementData, w, size - r); w += size - r; } if (w != size) { // 垃圾回收 for (int i = w; i < size; i++) elementData[i] = null; modCount += size - w; size = w; modified = true; } } return modified; }
输出流和输入流
/** * 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 ensureCapacityInternal(size); Object[] a = elementData; // Read in all elements in the proper order. for (int i=0; i<size; i++) { a[i] = s.readObject(); } } }
三个不同类型的迭代器
/** * 获取指定index开始的迭代器 * @throws index非法,抛出 :IndexOutOfBoundsException */ public ListIterator<E> listIterator(int index) { if (index < 0 || index > size) // 检查下标是否合法 throw new IndexOutOfBoundsException("Index: "+index); return new ListItr(index); } /** * 获取所有元素的迭代器,该迭代器,可以向前也可以先后遍历,可以更新元素 * @see #listIterator(int) */ public ListIterator<E> listIterator() { return new ListItr(0); } /** * 获取所有元素的迭代器 ,只可以向后遍历元素 */ public Iterator<E> iterator() { return new Itr(); }
内部类实现Itr迭代器
只能够向后遍历
private class Itr implements Iterator<E> { int cursor; // index of next element to return int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount; public boolean hasNext() { // 是否结束 return cursor != size; } @SuppressWarnings("unchecked") public E next() { // 下一个位置 checkForComodification(); // 运行记录最大值 int i = cursor; // 当前元素 if (i >= size) // 越界 throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) // 越界 throw new ConcurrentModificationException(); cursor = i + 1; // 下一个位置 return (E) elementData[lastRet = i]; // 返回当前元素 } public void remove() { // 删除 if (lastRet < 0) // 非法 throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.remove(lastRet);// 删除 cursor = lastRet; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }
ListItr 迭代器,继承Itr,并增加了前驱遍历、更新元素的方法
private class ListItr extends Itr implements ListIterator<E> { ListItr(int index) { super(); cursor = index; } public boolean hasPrevious() { // 是否有前驱 return cursor != 0; } public int nextIndex() { // 下一个位置 return cursor; } public int previousIndex() { // 前驱id return cursor - 1; } @SuppressWarnings("unchecked") public E previous() { // 前驱元素 checkForComodification(); int i = cursor - 1; if (i < 0) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i; return (E) elementData[lastRet = i]; } public void set(E e) { // 设置元素 if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.set(lastRet, e); } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } public void add(E e) { // 添加元素 checkForComodification(); try { int i = cursor; ArrayList.this.add(i, e); cursor = i + 1; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } }
获取子数组,以及其迭代器代码,和上面很类似
/* @throws IndexOutOfBoundsException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ public List<E> subList(int fromIndex, int toIndex) { subListRangeCheck(fromIndex, toIndex, size); return new SubList(this, 0, fromIndex, toIndex); } static void subListRangeCheck(int fromIndex, int toIndex, int size) { if (fromIndex < 0) throw new IndexOutOfBoundsException("fromIndex = " + fromIndex); if (toIndex > size) throw new IndexOutOfBoundsException("toIndex = " + toIndex); if (fromIndex > toIndex) throw new IllegalArgumentException("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")"); } private class SubList extends AbstractList<E> implements RandomAccess { private final AbstractList<E> parent; private final int parentOffset; private final int offset; int size; SubList(AbstractList<E> parent, int offset, int fromIndex, int toIndex) { this.parent = parent; this.parentOffset = fromIndex; this.offset = offset + fromIndex; this.size = toIndex - fromIndex; this.modCount = ArrayList.this.modCount; } public E set(int index, E e) { rangeCheck(index); checkForComodification(); E oldValue = ArrayList.this.elementData(offset + index); ArrayList.this.elementData[offset + index] = e; return oldValue; } public E get(int index) { rangeCheck(index); checkForComodification(); return ArrayList.this.elementData(offset + index); } public int size() { checkForComodification(); return this.size; } public void add(int index, E e) { rangeCheckForAdd(index); checkForComodification(); parent.add(parentOffset + index, e); this.modCount = parent.modCount; this.size++; } public E remove(int index) { rangeCheck(index); checkForComodification(); E result = parent.remove(parentOffset + index); this.modCount = parent.modCount; this.size--; return result; } protected void removeRange(int fromIndex, int toIndex) { checkForComodification(); parent.removeRange(parentOffset + fromIndex, parentOffset + toIndex); this.modCount = parent.modCount; this.size -= toIndex - fromIndex; } public boolean addAll(Collection<? extends E> c) { return addAll(this.size, c); } public boolean addAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index); int cSize = c.size(); if (cSize==0) return false; checkForComodification(); parent.addAll(parentOffset + index, c); this.modCount = parent.modCount; this.size += cSize; return true; } public Iterator<E> iterator() { return listIterator(); } public ListIterator<E> listIterator(final int index) { checkForComodification(); rangeCheckForAdd(index); final int offset = this.offset; return new ListIterator<E>() { int cursor = index; int lastRet = -1; int expectedModCount = ArrayList.this.modCount; public boolean hasNext() { return cursor != SubList.this.size; } @SuppressWarnings("unchecked") public E next() { checkForComodification(); int i = cursor; if (i >= SubList.this.size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (offset + i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; return (E) elementData[offset + (lastRet = i)]; } public boolean hasPrevious() { return cursor != 0; } @SuppressWarnings("unchecked") public E previous() { checkForComodification(); int i = cursor - 1; if (i < 0) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (offset + i >= elementData.length) throw new ConcurrentModificationException(); cursor = i; return (E) elementData[offset + (lastRet = i)]; } public int nextIndex() { return cursor; } public int previousIndex() { return cursor - 1; } public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { SubList.this.remove(lastRet); cursor = lastRet; lastRet = -1; expectedModCount = ArrayList.this.modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } public void set(E e) { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.set(offset + lastRet, e); } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } public void add(E e) { checkForComodification(); try { int i = cursor; SubList.this.add(i, e); cursor = i + 1; lastRet = -1; expectedModCount = ArrayList.this.modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } final void checkForComodification() { if (expectedModCount != ArrayList.this.modCount) throw new ConcurrentModificationException(); } }; } public List<E> subList(int fromIndex, int toIndex) { subListRangeCheck(fromIndex, toIndex, size); return new SubList(this, offset, fromIndex, toIndex); } private void rangeCheck(int index) { if (index < 0 || index >= this.size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } private void rangeCheckForAdd(int index) { if (index < 0 || index > this.size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } private String outOfBoundsMsg(int index) { return "Index: "+index+", Size: "+this.size; } private void checkForComodification() { if (ArrayList.this.modCount != this.modCount) throw new ConcurrentModificationException(); } }
相关文章推荐
- Spring4.1新特性——异步调度和事件机制的异常处理
- 一次PHP代码上线遇到的问题
- ubuntu bluetooth 配对过程
- 深入推荐引擎相关算法 - 协同过滤
- 解决首次启动程序白屏时间过长的问题
- android实现动画自动播放的渐变欢迎页面
- No grammar constraints (DTD or XML schema).....两种解决方法
- 一步一步学POI(java操作office类)1
- IOS,利用归档保存少量数据
- UTF8 与 UTF8 +BOM 区别
- 分享一个高手的python学习随笔。对于入门的新手有很大帮助
- python相关
- 最全的IMSI获取手机号段、归属地java代码
- 拼图框架-- 中国版的Bootstrap
- OSG3.5.1 + Qt5.4.2 + VS2010 + CMake3.4.3 安装说明
- WebView执行javascript遇到的坑
- C++ bitmap
- <LeetCode> 题9:Fizz Buzz问题
- Python 基础语法学习笔记
- ASP.Net Core-依赖注入IoC