死磕JDK源码之ArrayList
Posted sakura1027
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了死磕JDK源码之ArrayList相关的知识,希望对你有一定的参考价值。
ArrayList即动态数组,实现了动态的添加和减少元素
RandomAccess接口
标记接口,实现RandomAccess接口的类支持快速随机访问
Cloneable接口
没有实现Cloneable接口的类调用clone方法会抛出CloneNotSupportedException
Object提供的clone方法是浅度复制
Serializable接口
标记接口,实现Serializable接口的类可以被序列化
Iterable接口
实现Iterable接口的类支持for-each循环
AbstractCollection类
提供了Collection接口的骨干实现
contains
1 public boolean contains(Object o) { 2 Iterator<E> it = iterator();//调用自己的iterator()方法 3 if (o == null) {//对o是null值进行判断(注意是等号) 4 while (it.hasNext()) 5 if (it.next() == null) 6 return true; 7 } else {//迭代器依次遍历,如果有和o一样的元素,返回true并跳出循环 8 while (it.hasNext()) 9 /* 10 用元素所在类的equals()方法判断是否相等所以若存入 11 其中的元素是自定义对象则需要重写其equals()方法 12 */ 13 if (o.equals(it.next())) 14 return true; 15 } 16 return false;//遍历结束仍然没有与o相同的元素就返回false 17 }
toString
1 public String toString() { 2 Iterator<E> it = iterator(); 3 if (!it.hasNext())//对于空集合直接返回[] 4 return "[]"; 5 StringBuilder sb = new StringBuilder(); 6 sb.append(\'[\'); 7 for (;;) { 8 E e = it.next(); 9 sb.append(e == this ? "(this Collection)" : e);//防止出现死循环 10 if (!it.hasNext()) 11 return sb.append(\']\').toString(); 12 sb.append(\',\').append(\' \'); 13 } 14 }
AbstractList类
提供了List接口的骨干实现
迭代器实现
1 /* 2 内部类实现了迭代器接口,实现了对于元素的遍历 3 同时也解释了不能还没有调用next就remove和不能连续两次remove的原因: 4 未调用next就remove,lastRet的值为-1,会抛出IllegalStateException 5 而在第一次调用remove后,lastRet的值会置为-1,如果再次调用remove也会抛出异常 6 */ 7 private class Itr implements Iterator<E> { 8 int cursor = 0;//游标,表示下一个要访问的元素 9 int lastRet = -1;//表示上一个访问的元素 10 int expectedModCount = modCount;//对修改次数的期望值 11 public boolean hasNext() { 12 return cursor != size(); 13 } 14 public E next() { 15 checkForComodification();//检查遍历时集合有没有被修改过 fail-fast 16 try { 17 /* 18 E next=get(cursor); 19 lastRet=cursor++; 20 return next; 21 */ 22 int i = cursor; 23 E next = get(i);//获取元素 24 lastRet = i;//lastRet记录获取到的元素的索引 25 cursor = i + 1;//准备获取下一个元素 26 return next; 27 } catch (IndexOutOfBoundsException e) { 28 checkForComodification(); 29 throw new NoSuchElementException(); 30 } 31 } 32 public void remove() { 33 if (lastRet < 0) 34 throw new IllegalStateException(); 35 checkForComodification(); 36 try { 37 //调用remove方法删除上一个访问的元素 38 AbstractList.this.remove(lastRet); 39 if (lastRet < cursor) 40 cursor--; 41 /* 42 删除后把lastRet置为-1,连续无间隔调用remove抛出 43 IllegalStateException 44 */ 45 lastRet = -1; 46 expectedModCount = modCount; 47 } catch (IndexOutOfBoundsException e) { 48 throw new ConcurrentModificationException(); 49 } 50 } 51 final void checkForComodification() { 52 if (modCount != expectedModCount) 53 throw new ConcurrentModificationException();//并发修改异常 54 } 55 } 56 /* 57 支持在调用next或者previous后,添加元素 58 调用next时,调用add,add方法会在cursor的位置上添加元素,并把cursor+1使得next的 59 调用无法返回添加的元素 60 调用previous时,调用add,add方法会在已经返回的元素位置处添加元素,并把cursor+1 61 下次返回的会是cursor-1元素,即新添加的元素 62 */ 63 private class ListItr extends Itr implements ListIterator<E> { 64 ListItr(int index) { 65 cursor = index; 66 } 67 public boolean hasPrevious() { 68 return cursor != 0; 69 } 70 public E previous() { 71 checkForComodification(); 72 try { 73 /* 74 E previous=get(--cursor); 75 lastRet=cursor; 76 return previous; 77 */ 78 int i = cursor - 1; 79 E previous = get(i); 80 /* 81 结束方法调用时,cursor停留在返回的元素的位置上,这点与next不同 82 */ 83 lastRet = cursor = i; 84 return previous; 85 } catch (IndexOutOfBoundsException e) { 86 checkForComodification(); 87 throw new NoSuchElementException(); 88 } 89 } 90 public int nextIndex() { 91 return cursor; 92 } 93 public int previousIndex() { 94 return cursor - 1; 95 } 96 public void set(E e) {//用指定元素替换next或者previous返回的最后一个元素 97 if (lastRet < 0) 98 throw new IllegalStateException(); 99 checkForComodification(); 100 try { 101 AbstractList.this.set(lastRet, e); 102 expectedModCount = modCount; 103 } catch (IndexOutOfBoundsException ex) { 104 throw new ConcurrentModificationException(); 105 } 106 } 107 public void add(E e) {//插入指定元素到next返回的下一个元素的前面(如果有的话) 108 checkForComodification(); 109 try { 110 int i = cursor; 111 AbstractList.this.add(i, e); 112 lastRet = -1; 113 cursor = i + 1;//add方法使游标向前移动了一位 114 expectedModCount = modCount; 115 } catch (IndexOutOfBoundsException ex) { 116 throw new ConcurrentModificationException(); 117 } 118 } 119 }
equals
1 /* 2 1.判断比较对象是否为自己本身,如果是,返回true 3 2.判断比较对象是不是一个List,如果不是,返回false 4 3.迭代比较两个list公共长度上的元素,发现有不相同的返回false 5 4.两个list的长度不一样返回false 6 为什么不在循环之前判断两个list的size()是否一样,不一样直接返回false, 7 一样在进行循环判断比较所有元素是否相同? 8 */ 9 public boolean equals(Object o) {//只有两个列表的元素以及顺序完全一样才返回true 10 if (o == this) 11 return true; 12 if (!(o instanceof List))//判断o这个引用真正指向的类 13 return false; 14 ListIterator<E> e1 = listIterator(); 15 ListIterator<?> e2 = ((List<?>) o).listIterator(); 16 while (e1.hasNext() && e2.hasNext()) { 17 E o1 = e1.next(); 18 Object o2 = e2.next(); 19 if (!(o1 == null ? o2 == null : o1.equals(o2))) 20 return false; 21 } 22 return !(e1.hasNext() || e2.hasNext()); 23 }
ArrayList类
1 package java.util; 2 import java.util.function.Consumer; 3 import java.util.function.Predicate; 4 import java.util.function.UnaryOperator; 5 public class ArrayList<E> extends AbstractList<E> 6 implements List<E>, RandomAccess, Cloneable, java.io.Serializable 7 { 8 //Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的 9 private static final long serialVersionUID = 8683452581122892189L; 10 //默认初始化容量为10 11 private static final int DEFAULT_CAPACITY = 10; 12 //空的对象数组(用于new ArrayList(0)的初始化) 13 private static final Object[] EMPTY_ELEMENTDATA = {}; 14 //用于new ArrayList()的初始化 15 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; 16 //真正保存数据的数组 transient表示不可序列化 17 transient Object[] elementData; 18 //ArrayList的实际元素数量 19 private int size; 20 //构造一个具有指定初始容量的空列表 21 public ArrayList(int initialCapacity) { 22 if (initialCapacity > 0) { 23 this.elementData = new Object[initialCapacity]; 24 } else if (initialCapacity == 0) { 25 this.elementData = EMPTY_ELEMENTDATA; 26 } else { 27 throw new IllegalArgumentException("Illegal Capacity: "+ 28 initialCapacity); 29 } 30 } 31 //无参构造 32 public ArrayList() { 33 this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; 34 } 35 //构造一个包含指定集合c元素的列表 36 public ArrayList(Collection<? extends E> c) { 37 elementData = c.toArray(); 38 if ((size = elementData.length) != 0) { 39 //类型检查 40 if (elementData.getClass() != Object[].class) 41 elementData = Arrays.copyOf(elementData, size, Object[].class); 42 } else { 43 this.elementData = EMPTY_ELEMENTDATA; 44 } 45 } 46 //调整ArrayList的实际容量为size 47 public void trimToSize() { 48 //modCount记录修改次数+1 49 modCount++; 50 if (size < elementData.length) { 51 elementData = (size == 0) 52 ? EMPTY_ELEMENTDATA 53 : Arrays.copyOf(elementData, size); 54 } 55 } 56 public void ensureCapacity(int minCapacity) { 57 int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) 58 ? 0 : DEFAULT_CAPACITY; 59 if (minCapacity > minExpand) { 60 ensureExplicitCapacity(minCapacity); 61 } 62 } 63 private void ensureCapacityInternal(int minCapacity) { 64 //如果实际存储数组是空数组 则最小需要容量就是默认容量 65 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { 66 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); 67 } 68 ensureExplicitCapacity(minCapacity); 69 } 70 private void ensureExplicitCapacity(int minCapacity) { 71 modCount++; 72 //如果数组(elementData)的长度小于最小需要的容量(minCapacity)就扩容 73 if (minCapacity - elementData.length > 0) 74 grow(minCapacity); 75 } 76 /* 77 这个-8是为了减少出错的几率,避免一些机器内存溢出,最大长度依然是Integer.MAX_VALUE 78 并不是Integer.MAX_VALUE-8(通过hugeCapacity()方法调整) 79 */ 80 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; 81 private void grow(int minCapacity) { 82 int oldCapacity = elementData.length; 83 //扩容为原来的1.5倍 84 int newCapacity = oldCapacity + (oldCapacity >> 1); 85 //如果扩容1.5倍仍小于最小需要容量(针对addAll方法),就直接扩容为最小需要容量 86 if (newCapacity - minCapacity < 0) 87 newCapacity = minCapacity; 88 //若超出MAX_ARRAY_SIZE,调用hugeCapacity调整 89 if (newCapacity - MAX_ARRAY_SIZE > 0) 90 newCapacity = hugeCapacity(minCapacity); 91 //复制元素 92 elementData = Arrays.copyOf(elementData, newCapacity); 93 } 94 private static int hugeCapacity(int minCapacity) { 95 //溢出 96 if (minCapacity < 0) 97 throw new OutOfMemoryError(); 98 return (minCapacity > MAX_ARRAY_SIZE) ? 99 Integer.MAX_VALUE : 100 MAX_ARRAY_SIZE; 101 } 102 //返回元素数 103 public int size() { 104 return size; 105 } 106 //判断列表是否为空 107 public boolean isEmpty() { 108 return size == 0; 109 } 110 //判断是否包含指定元素 111 public boolean contains(Object o) { 112 return indexOf(o) >= 0; 113 } 114 //返回o第一次出现的索引,没有就返回-1 115 public int indexOf(Object o) { 116 //判断o是否为null,避免出现o.equals空指针异常 117 if (o == null) { 118 for (int i = 0; i < size; i++) 119 if (elementData[i]==null) 120 return i; 121 } else { 122 for (int i = 0; i < size; i++) 123 if (o.equals(elementData[i])) 124 return i; 125 } 126 return -1; 127 } 128 //返回o最后一次出现的索引,没有就返回-1 129 public int lastIndexOf(Object o) { 130 if (o == null) { 131 for (int i = size-1; i >= 0; i--) 132 if (elementData[i]==null) 133 return i; 134 } else { 135 for (int i = size-1; i >= 0; i--) 136 if (o.equals(elementData[i])) 137 return i; 138 } 139 return -1; 140 } 141 //浅度复制 142 public Object clone() { 143 try { 144 ArrayList<?> v = (ArrayList<?>) super.clone(); 145 v.elementData = Arrays.copyOf(elementData, size); 146 v.modCount = 0; 147 return v; 148 } catch (CloneNotSupportedException e) { 149 //不会发生,因为已经实现了Cloneable接口 150 throw new InternalError(e); 151 } 152 } 153 //集合转换为数组 154 public Object[] toArray() { 155 return Arrays.copyOf(elementData, size); 156 } 157 //通过泛型约束返回指定类型的数组 158 @SuppressWarnings("unchecked") 159 public <T> T[] toArray(T[] a) { 160 if (a.length < size) 161 return (T[]) Arrays.copyOf(elementData, size, a.getClass()); 162 /* 163 elementData:源数组 0:源数组要复制的起始位置 164 a:目的数组 0:目的数组要复制的起始位置 165 size:复制的长度 166 */ 167 System.arraycopy(elementData, 0, a, 0, size); 168 if (a.length > size) 169 a[size] = null; 170 return a; 171 } 172 //返回数组指定位置元素(没有进行下标检查) 173 @SuppressWarnings("unchecked") 174 E elementData(int index) { 175 return (E) elementData[index]; 176 } 177 //返回列表指定位置元素 178 public E get(int index) { 179 rangeCheck(index); 180 return elementData(index); 181 } 182 //用element替代指定位置上的元素 183 public E set(int index, E element) { 184 rangeCheck(index); 185 E oldValue = elementData(index); 186 elementData[index] = element; 187 //返回之前位于index上的元素 188 死磕JDK源码之Thread死磕 java集合之CopyOnWriteArrayList源码分析