Java中的容器(集合)之ArrayList源码解析
2019-10-08 09:09:10来源:博客园 阅读 ()
Java中的容器(集合)之ArrayList源码解析
1、ArrayList源码解析
源码解析:
- 如下源码来自JDK8(如需查看ArrayList扩容源码解析请跳转至《Java中的容器(集合)》第十条):。
package java.util; import java.util.function.Consumer; import java.util.function.Predicate; import java.util.function.UnaryOperator; import sun.misc.SharedSecrets; //其中实现了RandomAccess接口表示支持随机访问 public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { //序列号 private static final long serialVersionUID = 8683452581122892189L; /** * 默认初始容量 */ private static final int DEFAULT_CAPACITY = 10; /** * 共享的空数组实例(用于空实例) * 当ArrayList(int initialCapacity),ArrayList(Collection<? extends E> c)中的容量等于0的时候使用 */ private static final Object[] EMPTY_ELEMENTDATA = {}; /** * 共享的空数组实例(用于默认大小的空实例) * 将其与EMPTY_ELEMENTDATA区分开来,主要是为了知道第一次添加元素的时候需要扩容多少 * 用于ArrayList()构造器 */ private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; /** * ArrayList保存有序元素的数组 * ArraylList容量为数组容量 * 任何空数组都使用 elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA * 当第一次添加元素的时候其容量将会扩容至 DEFAULT_CAPACITY(10) */ transient Object[] elementData; // non-private to simplify nested class access /** * ArrayList的大小(包含元素的数量) * @serial */ private int size; /** * 带指定容量参数的构造器,如果元素数量较大的话,可以使用此构造器,防止频繁扩容造成的性能损失 */ public ArrayList(int initialCapacity) { //如果传入值大于0,则创建一个该容量大小的数组。 if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { //否则如果传入值等于0,则创建默认空数组 this.elementData = EMPTY_ELEMENTDATA; } else { //如果小于0则抛出异常 throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } } /** * 默认构造函数,其初始容量为10(注意,这里一开始其实是一个空数组,只是当add时才会进行扩容至10的操作,一定程度上减小了内存消耗。) */ public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } /** * 构造一个包含指定集合元素的列表,元素顺序由集合的迭代器所返回。 */ public ArrayList(Collection<? extends E> c) { //集合转数组 elementData = c.toArray(); //指定集合含有元素 if ((size = elementData.length) != 0) { // c.toArray可能不会返回Object[] (see 6260652) //使用反射进行运行时判断elementData是否属于Object[] if (elementData.getClass() != Object[].class) //拷贝数组 elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // 由空数组代替 this.elementData = EMPTY_ELEMENTDATA; } } /** * 修改ArrayList容量为list的当前大小 * 一个应用可以使用此操作来最小化一个ArrayList的存储 */ public void trimToSize() { modCount++; //如果当前数组元素个数小于数组容量 if (size < elementData.length) { //没有元素返回空数组,否则返回元素个数的数组。 elementData = (size == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size); } } /** * 如果有必要去增加ArrayList的容量,请确保它至少可以容纳由最小容量参数指定的元素数量 * @param minCapacity 所需的最小容量 */ public void ensureCapacity(int minCapacity) { //默认最小容量,空数组以及默认大小10 int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) // any size if not default element table ? 0 // larger than default for default empty table. It's already // supposed to be at default size. : DEFAULT_CAPACITY; //如果传入容量大于最小容量,则进行扩容 if (minCapacity > minExpand) { ensureExplicitCapacity(minCapacity); } } private static int calculateCapacity(Object[] elementData, int minCapacity) { //如果elementData为默认空数组,则比较传入值与默认值(10),返回两者中的较大值 //elementData为默认空数组指的是通过ArrayList()这个构造器创建的ArrayList对象 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { return Math.max(DEFAULT_CAPACITY, minCapacity); } //返回传入值 return minCapacity; } private void ensureCapacityInternal(int minCapacity) { //先通过calculateCapacity方法计算最终容量,以确认实际容量 ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); } private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code //如果最终确认容量大于数组容量,则进行grow()扩容 if (minCapacity - elementData.length > 0) grow(minCapacity); } /** * 可分配数组最大大小 */ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; /** * 增加ArrayList的容量,以确保它至少可以容纳由最小容量参数指定的元素数量 * @param minCapacity 所需的最小容量 */ private void grow(int minCapacity) { // overflow-conscious code //oldCapacity表示旧容量 int oldCapacity = elementData.length; //newCapacity表示新容量,计算规则为旧容量+旧容量的0.5,即旧容量的1.5倍。如果超过int的最大值会返回一个负数。 //oldCapacity >> 1表示右移一位,对应除以2的1次方。 int newCapacity = oldCapacity + (oldCapacity >> 1); //如果新容量小于最小容量,则将最小容量赋值给新容量(有时手动扩容可能也会返回<0,对应方法为ensureCapacity()) if (newCapacity - minCapacity < 0) newCapacity = minCapacity; //如果新容量大于MAX_ARRAY_SIZE,则执行hugeCapacity(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) { //如果最小容量超过了int的最大值,minCapacity会是一个负数,此时抛出内存溢出错误 if (minCapacity < 0) // overflow throw new OutOfMemoryError(); //比较最小容量是否大于MAX_ARRAY_SIZE,如果是则返回Integer.MAX_VALUE,否则返回MAX_ARRAY_SIZE return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; } /** * 返回列表元素数 */ public int size() { return size; } /** * 如果列表不包含元素,返回true */ public boolean isEmpty() { return size == 0; } /** * 如果列表包含指定元素,返回true */ public boolean contains(Object o) { //返回此列表中指定元素第一次出现的索引,如果列表中不包含指定元素,则为-1 return indexOf(o) >= 0; } /** * 返回此列表中指定元素第一次出现的索引,如果列表中不包含指定元素,则为-1 */ 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; } /** * 返回此列表中指定元素最后一次出现的索引,如果列表中不包含指定元素,则为-1 */ 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; } /** * 返回ArrayList实例的一个浅拷贝,列表中的元素不会被拷贝 */ public Object clone() { try { ArrayList<?> v = (ArrayList<?>) 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(e); } } /** * 以正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组。 * 返回的数组将是“安全的”,因为该列表不保留对它的引用。 (换句话说,这个方法必须分配一个新的数组)。 * 因此,调用者可以自由地修改返回的数组。 此方法充当基于阵列和基于集合的API之间的桥梁。 */ public Object[] toArray() { return Arrays.copyOf(elementData, size); } /** * 以正确的顺序返回一个包含此列表中所有元素的数组(从第一个到最后一个元素); * 返回的数组的运行时类型是指定数组的运行时类型。 如果列表适合指定的数组,则返回其中。 * 否则,将为指定数组的运行时类型和此列表的大小分配一个新数组。 * 如果列表适用于指定的数组,其余空间(即数组的列表数量多于此元素),则紧跟在集合结束后的数组中的元素设置为null 。 *(这仅在调用者知道列表不包含任何空元素的情况下才能确定列表的长度。) */ @SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { if (a.length < size) //创建一个新的运行时类型数组,内容为ArrayList数组的 return (T[]) Arrays.copyOf(elementData, size, a.getClass()); System.arraycopy(elementData, 0, a, 0, size); if (a.length > size) a[size] = null; return a; } // 位置访问操作 @SuppressWarnings("unchecked") E elementData(int index) { return (E) elementData[index]; } /** * 返回此列表中指定位置的元素 */ public E get(int index) { //检查索引是否越界 rangeCheck(index); return elementData(index); } /** * 用指定元素替换列表中的指定位置的元素 */ 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); // Increments modCount!! //新加入的元素是添加在了数组的末尾,随后数组size自增。 elementData[size++] = e; return true; } /** * 插入指定元素到此列表中的指定位置 * 先调用 rangeCheckForAdd 对index进行界限检查;然后调用 ensureCapacityInternal 方法保证capacity足够大; * 再将从index开始之后的所有成员后移一个位置;将element插入index位置;最后size加1。 */ 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++; } /** * 将列表中指定位置的元素移除,后续所有元素移到左端(从他们的索引中减去一个) */ 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; // 清理工作交给GC return oldValue; } /** * 从列表中移除第一次出现的指定元素,如果不存在,则不更改 */ 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 } /** * 移除列表中的所有元素,之后会返回一个空数组 */ public void clear() { modCount++; // clear to let GC do its work for (int i = 0; i < size; i++) elementData[i] = null; size = 0; } /** * 将指定集合中的元素以Iterator返回的顺序,追加到列表末尾 */ 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; } /** * 将指定集合中的元素以Iterator返回的顺序,插入到指定位置 */ public boolean addAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index); Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); // Increments modCount 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; } /** * 移除[fromIndex,toIndex)之间的元素,后续元素移到左端 */ 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); for (int i = newSize; i < size; i++) { elementData[i] = null; } size = newSize; } /** *检查给定索引是否在界限内。 */ private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } /** * add and addAll使用的rangeCheck */ private void rangeCheckForAdd(int index) { if (index > size || index < 0) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } /** * 返回 an IndexOutOfBoundsException 的细节信息 */ private String outOfBoundsMsg(int index) { return "Index: "+index+", Size: "+size; } /** * 从列表中移除指定集合包含的所有元素 */ public boolean removeAll(Collection<?> c) { Objects.requireNonNull(c); return batchRemove(c, false); } /** * 保留此列表中指定集合的所有元素 */ public boolean retainAll(Collection<?> c) { Objects.requireNonNull(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) 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) { // clear to let GC do its work for (int i = w; i < size; i++) elementData[i] = null; modCount += size - w; size = w; modified = true; } } return modified; } /** * 保存ArrayList状态到一个流中(即序列化) */ 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(); } } /** * 从一个流中读取ArrayList(即反序列化) */ 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(); } } } /** * 从列表中的指定位置开始,返回之后所有元素的列表迭代器(按正确的顺序) * 指定的索引表示初始调用将返回的第一个元素为next 。 初始调用previous将返回指定索引减1的元素。 * 返回的列表迭代器是fail-fast 。 */ public ListIterator<E> listIterator(int index) { if (index < 0 || index > size) throw new IndexOutOfBoundsException("Index: "+index); return new ListItr(index); } /** * 返回列表中的包含所有元素的列表迭代器(按正确的顺序)。 * 返回的列表迭代器是fail-fast 。 */ public ListIterator<E> listIterator() { return new ListItr(0); } /** * 以正确的顺序返回列表中的包含所有元素的迭代器。 * 返回的迭代器是fail-fast 。 */ public Iterator<E> iterator() { return new Itr(); } @Override public void forEach(Consumer<? super E> action) { Objects.requireNonNull(action); final int expectedModCount = modCount; @SuppressWarnings("unchecked") final E[] elementData = (E[]) this.elementData; final int size = this.size; for (int i=0; modCount == expectedModCount && i < size; i++) { action.accept(elementData[i]); } if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } } @Override public boolean removeIf(Predicate<? super E> filter) { Objects.requireNonNull(filter); // figure out which elements are to be removed // any exception thrown from the filter predicate at this stage // will leave the collection unmodified int removeCount = 0; final BitSet removeSet = new BitSet(size); final int expectedModCount = modCount; final int size = this.size; for (int i=0; modCount == expectedModCount && i < size; i++) { @SuppressWarnings("unchecked") final E element = (E) elementData[i]; if (filter.test(element)) { removeSet.set(i); removeCount++; } } if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } // shift surviving elements left over the spaces left by removed elements final boolean anyToRemove = removeCount > 0; if (anyToRemove) { final int newSize = size - removeCount; for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) { i = removeSet.nextClearBit(i); elementData[j] = elementData[i]; } for (int k=newSize; k < size; k++) { elementData[k] = null; // Let gc do its work } this.size = newSize; if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } modCount++; } return anyToRemove; } @Override @SuppressWarnings("unchecked") public void replaceAll(UnaryOperator<E> operator) { Objects.requireNonNull(operator); final int expectedModCount = modCount; final int size = this.size; for (int i=0; modCount == expectedModCount && i < size; i++) { elementData[i] = operator.apply((E) elementData[i]); } if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } modCount++; } @Override @SuppressWarnings("unchecked") public void sort(Comparator<? super E> c) { final int expectedModCount = modCount; Arrays.sort((E[]) elementData, 0, size, c); if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } modCount++; } }
(以上所有内容皆为个人笔记,如有错误之处还望指正。)
原文链接:https://www.cnblogs.com/xihuantingfeng/p/11618015.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:Java中的容器(集合)
下一篇:STS安装Drools
- 国外程序员整理的Java资源大全(全部是干货) 2020-06-12
- 2020年深圳中国平安各部门Java中级面试真题合集(附答案) 2020-06-11
- 2020年java就业前景 2020-06-11
- 04.Java基础语法 2020-06-11
- Java--反射(框架设计的灵魂)案例 2020-06-11
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash