博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一点一点看JDK源码(三)java.util.ArrayList 前偏
阅读量:7069 次
发布时间:2019-06-28

本文共 34020 字,大约阅读时间需要 113 分钟。

一点一点看JDK源码(三)java.util.ArrayList

 

liuyuhang原创,未经允许禁止转载

本文举例使用的是JDK8的API

 

目录:

1.综述

  ArrayList是一个容量不固定的容器,为单列,有序集合,容量可扩容,扩容系数为1.5

  有最大值,一般达不到。

  ArrayList是线程不安全的,其扩容发生于集合修改的时候,如add,addAll等

  ArrayList底层使用的是Object数组,初始化内容为10个容量的元素

  使用ArrayList的时候,几种情况下实例化将更加提高效率

    ①仅仅使用基础增加功能作为容器临时使用

      List list = new ArrayList()

      这样可以使用较少的实例化方法

    ②使用ArrayList中的所有实例化方法时使用

      ArrayList list = new ArrayList()

      这样可以使用ArrayList所有的方法

    ③如果你能确定这个集合的容量,最好指定其容量,

      扩容也是一种算法,而且可能扩容多次,效率不高,如:

      ArrayList list = new ArrayList(22)

    ④如果该ArrayList的长度巨大,并且不确定,只用于容器临时使用

      建议使用LinkedList进行接收参数,然后再转化为ArrayList,如:

      LinkedList list = new LinkedList();

      //some operations

      ArrayList listArr = new ArrayList(list);

  

2.关注点

  • Collection
  • List
  • LinkedList
  • Vector

  关注点

    Collection为父接口的父接口

    List为父接口

    LinkedList为List的链表实现,ArrayList为List的数组实现

    Vector几乎不去用,他是List的另一种数组实现,但是线程安全

 

  虽然类注释上的@see只有这些,但是个人认为,

  应该重点关注一下AbstractList抽象类,RandomAccess,Cloneable这两个接口,序列化接口关注度真心不高

  对于接口的实现关系,哪些是List通用的,哪些内容已经在AbstractList抽象类中已经定义了,应该过一下的

 

3.源码解析

  放源码如下,注解有些删掉,对于类,内部类,方法,构造等进行了简要的说明注释

 

  内容比较多,建议慢慢看完,如果jdk1.8新增的看不懂,可以暂时搁置,略过

  我也不保证对于jdk1.8的部分注释是正确的。

 

1 public class ArrayList
extends AbstractList
implements List
, RandomAccess, Cloneable, java.io.Serializable{ 2 /** 3 * 序列化版本号 4 */ 5 private static final long serialVersionUID = 8683452581122892189L; 6 /** 7 * 默认容量。 8 */ 9 private static final int DEFAULT_CAPACITY = 10; 10 11 /** 12 * 以object数组作为类内共享实例容器。 13 */ 14 private static final Object[] EMPTY_ELEMENTDATA = {}; 15 16 /** 17 * 以object数组作为类内共享实例容器,使用默认容量实例化时使用。 18 */ 19 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; 20 21 /** 22 * 以object数组作为容器缓自排序冲数组,注意没有private关键字,用于排序,当地一个元素添加的时候将转为默认容量 23 */ 24 transient Object[] elementData; // non-private to simplify nested class access 25 26 /** 27 * 缓存的size大小, 28 */ 29 private int size; 30 31 /** 32 * 带参构造,手动设置容器初始大小,若实例化时能确定大小,最好别使用默认扩展容量,将提高运行效率 33 */ 34 public ArrayList(int initialCapacity) { 35 if (initialCapacity > 0) { 36 this.elementData = new Object[initialCapacity]; //使用自排序缓冲数组 37 } else if (initialCapacity == 0) { 38 this.elementData = EMPTY_ELEMENTDATA; //使用默认数组 39 } else { 40 throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); //容量扩充参数异常 41 } 42 } 43 44 /** 45 * 无参构造,使用默认容器初始化大小 46 */ 47 public ArrayList() { 48 this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; 49 } 50 51 /** 52 * 带参构造器,将参数集合用数组工具类转成数组,并存入缓冲数组,对缓冲数组进行校验. 53 * 若转换后的数组并非object数组(内嵌套无法直接引用情况下),则使用数组工具类将该数组使用深度拷贝 54 */ 55 public ArrayList(Collection
c) { 56 elementData = c.toArray(); 57 if ((size = elementData.length) != 0) { 58 // c.toArray might (incorrectly) not return Object[] (see 6260652) 59 if (elementData.getClass() != Object[].class) 60 elementData = Arrays.copyOf(elementData, size, Object[].class); 61 } else { 62 // replace with empty array. 63 this.elementData = EMPTY_ELEMENTDATA; 64 } 65 } 66 67 /** 68 * 去除多余的数组申请空间,在内存紧张时会用到 69 */ 70 public void trimToSize() { 71 modCount++;//修改次数 72 if (size < elementData.length) { 73 elementData = (size == 0) 74 ? EMPTY_ELEMENTDATA 75 : Arrays.copyOf(elementData, size); 76 } 77 } 78 79 /** 80 * 对底层缓冲数组进行扩容的优化方法,如果已知该ArrayList容量,则可执行一次性扩容, 81 * 否则将在数组add的过程中进行动态扩容,效率较低 82 */ 83 public void ensureCapacity(int minCapacity) { 84 int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)? 0: DEFAULT_CAPACITY; 85 if (minCapacity > minExpand) { 86 ensureExplicitCapacity(minCapacity); 87 } 88 } 89 /** 90 * 重新计算ArrayList的size,在使用构造和扩容时调用 91 */ 92 private static int calculateCapacity(Object[] elementData, int minCapacity) { 93 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { 94 return Math.max(DEFAULT_CAPACITY, minCapacity); 95 } 96 return minCapacity; 97 } 98 99 /** 100 * 被add调用,内部调用calculatecapacity,用于扩容 101 */ 102 private void ensureCapacityInternal(int minCapacity) { 103 ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); 104 } 105 106 /** 107 * 被ensureCapacity调用,内部调用calculatecapacity,用于扩容或优化 108 */ 109 private void ensureExplicitCapacity(int minCapacity) { 110 modCount++; 111 // overflow-conscious code 112 if (minCapacity - elementData.length > 0) 113 grow(minCapacity); 114 } 115 116 /** 117 * 目标分配数组的容器大小,最大值要小于Integer.MAX_VALUE-8 118 */ 119 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; 120 121 /** 122 * 扩容 123 */ 124 private void grow(int minCapacity) { 125 int oldCapacity = elementData.length; //原容量 126 int newCapacity = oldCapacity + (oldCapacity >> 1); //新容量,扩容1.5倍,自查>>位运算 127 if (newCapacity - minCapacity < 0) //容量不足,则扩容 128 newCapacity = minCapacity; 129 if (newCapacity - MAX_ARRAY_SIZE > 0) //扩容超支,使用最大容 130 newCapacity = hugeCapacity(minCapacity); 131 // minCapacity is usually close to size, so this is a win: 132 elementData = Arrays.copyOf(elementData, newCapacity); 133 } 134 /** 135 * 被grow方法调用,扩容为最大 136 */ 137 private static int hugeCapacity(int minCapacity) { 138 if (minCapacity < 0) //参数错误,抛出异常 139 throw new OutOfMemoryError(); 140 return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; //返回最大容量 141 } 142 143 /** 144 * 获取当前size 145 */ 146 public int size() { 147 return size; 148 } 149 150 /** 151 * 判断当前是size是否为0,容器是否为空 152 */ 153 public boolean isEmpty() { 154 return size == 0; 155 } 156 157 /** 158 * 判断是否包含元素o,返回该元素的index是否大于等于0的判断,是为包含,否为不包含 159 */ 160 public boolean contains(Object o) { 161 return indexOf(o) >= 0; 162 } 163 164 /** 165 * 获取查询元素的index,若备查元素为null,则寻找空元素,返回index 166 * 若备查元素不为null,则使用equal判断该元素是否存在,并返回index 167 * 不存在则返回-1 168 * 被contains调用 169 */ 170 public int indexOf(Object o) { 171 if (o == null) { 172 for (int i = 0; i < size; i++) 173 if (elementData[i]==null) 174 return i; 175 } else { 176 for (int i = 0; i < size; i++) 177 if (o.equals(elementData[i])) 178 return i; 179 } 180 return -1; 181 } 182 183 /** 184 * 倒叙查询第一个出现的被查元素 185 */ 186 public int lastIndexOf(Object o) { 187 if (o == null) { 188 for (int i = size-1; i >= 0; i--) 189 if (elementData[i]==null) 190 return i; 191 } else { 192 for (int i = size-1; i >= 0; i--) 193 if (o.equals(elementData[i])) 194 return i; 195 } 196 return -1; 197 } 198 199 /** 200 * clone本实例数组,返回类型为Object,使用根类意为可转换为其他格式容器 201 */ 202 public Object clone() { 203 try { 204 ArrayList
v = (ArrayList
) super.clone(); 205 v.elementData = Arrays.copyOf(elementData, size); 206 v.modCount = 0; 207 return v; 208 } catch (CloneNotSupportedException e) { 209 throw new InternalError(e); 210 } 211 } 212 213 /** 214 * 将本实例转换为object数组,调用数组工具类拷贝 215 */ 216 public Object[] toArray() { 217 return Arrays.copyOf(elementData, size); 218 } 219 220 /** 221 * 将本实例转换为指定类型数组,调用数组工具类拷贝,并获得泛型的Class 222 */ 223 @SuppressWarnings("unchecked") 224 public
T[] toArray(T[] a) { 225 if (a.length < size) 226 // Make a new array of a's runtime type, but my contents: 227 return (T[]) Arrays.copyOf(elementData, size, a.getClass()); 228 System.arraycopy(elementData, 0, a, 0, size); 229 if (a.length > size) 230 a[size] = null; 231 return a; 232 } 233 234 /** 235 * 获取指定index的元素,被get方法调用,get方法内进行check,util包内的类可调用 236 */ 237 @SuppressWarnings("unchecked") 238 E elementData(int index) { 239 return (E) elementData[index]; 240 } 241 242 /** 243 * 获取指定元素的方法,使用rangeCheck进行index的check 244 */ 245 public E get(int index) { 246 rangeCheck(index); 247 return elementData(index); 248 } 249 250 /** 251 * 将指定index的值设置为指定值,使用rangeCheck进行index的check 252 */ 253 public E set(int index, E element) { 254 rangeCheck(index); 255 E oldValue = elementData(index); 256 elementData[index] = element; 257 return oldValue; 258 } 259 260 /** 261 * 容量+1的,在容器尾部添加元素 262 */ 263 public boolean add(E e) { 264 ensureCapacityInternal(size + 1); // Increments modCount!! 265 elementData[size++] = e; // 这个在数组尾部追加元素的写法很好用,前提是扩容 266 return true; // 有返回值的,应当接收 267 } 268 269 /** 270 * 在指定index添加指定元素,首先使用rangeCheckForAdd进行check,为保证数组操作的正确性,使用arraycopy来移动数组元素 271 */ 272 public void add(int index, E element) { 273 rangeCheckForAdd(index); 274 ensureCapacityInternal(size + 1); // Increments modCount!! 275 System.arraycopy(elementData, index, elementData, index + 1, size - index); 276 elementData[index] = element; 277 size++; 278 } 279 280 /** 281 * remove指定index的元素,并重构本实例 282 */ 283 public E remove(int index) { 284 rangeCheck(index); 285 modCount++; 286 E oldValue = elementData(index); 287 int numMoved = size - index - 1; 288 if (numMoved > 0) 289 System.arraycopy(elementData, index+1, elementData, index, numMoved); 290 elementData[--size] = null; // clear to let GC do its work 291 return oldValue; 292 } 293 294 /** 295 * remove指定元素,返回是否找到该元素并移除成功的boolean标记 296 */ 297 public boolean remove(Object o) { 298 if (o == null) { 299 for (int index = 0; index < size; index++) 300 if (elementData[index] == null) { 301 fastRemove(index); 302 return true; 303 } 304 } else { 305 for (int index = 0; index < size; index++) 306 if (o.equals(elementData[index])) { 307 fastRemove(index); 308 return true; 309 } 310 } 311 return false; 312 } 313 314 /* 315 * 内部使用,快速移除指定index的元素 316 */ 317 private void fastRemove(int index) { 318 modCount++; 319 int numMoved = size - index - 1; 320 if (numMoved > 0) 321 System.arraycopy(elementData, index+1, elementData, index, 322 numMoved); 323 elementData[--size] = null; // clear to let GC do its work 324 } 325 326 /** 327 * 清除本实例内部的所有元素,加速gc回收 328 */ 329 public void clear() { 330 modCount++; 331 // clear to let GC do its work 332 for (int i = 0; i < size; i++) 333 elementData[i] = null; 334 size = 0; 335 } 336 337 /** 338 * 添加指定集合到本实例中Object数组末尾 339 */ 340 public boolean addAll(Collection
c) { 341 Object[] a = c.toArray(); 342 int numNew = a.length; 343 ensureCapacityInternal(size + numNew); // Increments modCount 344 System.arraycopy(a, 0, elementData, size, numNew); 345 size += numNew; 346 return numNew != 0; 347 } 348 349 /** 350 * 从指定元素开始添加指定集合到本实例 351 */ 352 public boolean addAll(int index, Collection
c) { 353 rangeCheckForAdd(index); 354 Object[] a = c.toArray(); 355 int numNew = a.length; 356 ensureCapacityInternal(size + numNew); // Increments modCount 357 int numMoved = size - index; 358 if (numMoved > 0) 359 System.arraycopy(elementData, index, elementData, index + numNew, 360 numMoved); 361 System.arraycopy(a, 0, elementData, index, numNew); 362 size += numNew; 363 return numNew != 0; 364 } 365 366 /** 367 * 本类和子类可使用,移除指定范围的index的所有元素 368 */ 369 protected void removeRange(int fromIndex, int toIndex) { 370 modCount++; 371 int numMoved = size - toIndex; 372 System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved); 373 int newSize = size - (toIndex-fromIndex); 374 for (int i = newSize; i < size; i++) { 375 elementData[i] = null; 376 } 377 size = newSize; 378 } 379 380 /** 381 * 内部的index超限检测方法,当index超过size的时候,抛出index超限异常,在本类中被多次调用 382 */ 383 private void rangeCheck(int index) { 384 if (index >= size) 385 throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); 386 } 387 388 /** 389 * 同上,但是在add和addAll中专用 390 */ 391 private void rangeCheckForAdd(int index) { 392 if (index > size || index < 0) 393 throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); 394 } 395 396 /** 397 * index超限抛异常时使用,用来提示size和index的值 398 */ 399 private String outOfBoundsMsg(int index) { 400 return "Index: "+index+", Size: "+size; 401 } 402 403 /** 404 * 从本类实例中移除指定集合中所有元素的方法,返回值应接收 405 */ 406 public boolean removeAll(Collection
c) { 407 Objects.requireNonNull(c); 408 return batchRemove(c, false); 409 } 410 411 /** 412 * 从本类实例中保留指定集合中所有元素的方法,与removeAll相反 413 */ 414 public boolean retainAll(Collection
c) { 415 Objects.requireNonNull(c); 416 return batchRemove(c, true); 417 } 418 419 /** 420 * 内部调用,如果参数集合发生更改,则返回true 421 */ 422 private boolean batchRemove(Collection
c, boolean complement) { 423 final Object[] elementData = this.elementData; //获取本实例的所有元素 424 int r = 0, w = 0; //r用于遍历,w用于记录相同元素的数量,也用于记录容器的扩容标记 425 boolean modified = false; //标志位 426 try { 427 for (; r < size; r++) 428 if (c.contains(elementData[r]) == complement) //判断该元素是否被包含 429 elementData[w++] = elementData[r]; //包含则w++ 430 } finally { 431 // Preserve behavioral compatibility with AbstractCollection, 432 // even if c.contains() throws. 433 if (r != size) {
//集合有变化 434 System.arraycopy(elementData, r, elementData, w, size - r); 435 w += size - r; 436 } 437 if (w != size) {
//容量不相等 438 // clear to let GC do its work 439 for (int i = w; i < size; i++) 440 elementData[i] = null; 441 modCount += size - w; 442 size = w; 443 modified = true; //容量有变化,说明有交集,则返回true 444 } 445 } 446 return modified; 447 } 448 449 /** 450 * 将本实例对象写入流中,实际上只写入了modCount,size和element[i],其余的内容在实例化时候是不必要的,或者可恢复的 451 */ 452 private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{ 453 // Write out element count, and any hidden stuff 454 int expectedModCount = modCount; 455 s.defaultWriteObject(); 456 // Write out size as capacity for behavioural compatibility with clone() 457 s.writeInt(size); 458 // Write out all elements in the proper order. 459 for (int i=0; i

 

 

  本篇注释前偏,只是粗略的了解,中篇 和 后篇 将对其中的使用进行总结和举例。

 

以上!

 

转载于:https://www.cnblogs.com/liuyuhangCastle/p/9623526.html

你可能感兴趣的文章
系统出现非法操作错误解决对策
查看>>
xml文件对比或xml大字符串对比方法(蛮精简的)
查看>>
Weblogic产品模式切换与JVM切换
查看>>
论“性能需求分析”系列专题(一)之 性能需求剖析
查看>>
费波拉奇 递归
查看>>
PC 加入AD域的要求
查看>>
Enterprise Library 2.0 Hands On Lab 翻译(1):数据访问程序块(一)
查看>>
微软私有云分享(R2)17SCAC被精简的功能
查看>>
安装maildrop-2.0.4
查看>>
Spring Security身份认证之HelloSpringSecurity(附源码)
查看>>
WPF实例秀——不用属性也Binding
查看>>
打造Ubuntu下的SLAMP
查看>>
SoapUI实践:自动化测试、压力测试、持续集成
查看>>
Redis中Value使用hash类型的效率是普通String的两倍
查看>>
爪哇国新游记之八----读写文件及数组排序
查看>>
[Android]在Dagger 2中使用RxJava来进行异步注入(翻译)
查看>>
是技术还是态度,网易的视频Title
查看>>
ES 處於“initializing”狀態,此時主節點正在嘗試將分片分配到集群中的數據節點。 如果您看到分片仍處於初始化或未分配狀態太長時間,則可能是您的集群不穩定的警告信號。...
查看>>
切换RequiredFieldValidator和RegularExpressionValidator提示信息的控件
查看>>
基于类的封装[基础]
查看>>