ArrayList源码阅读.

//测试代码实现如下
private static void arrayList() {ArrayList<String> list = new ArrayList<String>();list.add("aaa");list.add("bbb");list.add("ccc");list.add("ddd");list.add("aaa");list.add("bbb");list.add("ccc");list.add("ddd");list.add("aaa");list.add("bbb");list.add("ccc");list.add("ddd");list.add(1, null);int size = list.size();for (int i = 0; i < size; i++) {System.out.println(list.get(i));}}

查看ArrayList<String>();的源码的时候可以发现如下:

  1. 其属性elementData被初始化为一个空的Object数组.
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

执行list.add("aaa");可以看到如下源码:

  1. 其中的size表示目前List中已经存储的元素的数量,目前为0.

  2. 开始执行添加元素操作.add(e, elementData, size);

protected transient int modCount = 0;
transient Object[] elementData; // non-private to simplify nested class access
private int size;
public boolean add(E e) {modCount++;add(e, elementData, size);return true;
}

进入add(e, elementData, size);可以看到如下源码:

  1. 已存储元素和当前的对象数组的长度相等,都是0.

  2. 执行数组扩容行动elementData = grow();

  3. 当目前对象数组已满时得到,size==elementData.length.

  4. 进入elementData = grow();,继续扩容.

  5. 通过最后两行代码给对象数组赋值.

private void add(E e, Object[] elementData, int s) {if (s == elementData.length)elementData = grow();elementData[s] = e;size = s + 1;
}

进入elementData = grow();可以看到如下源码:

  1. grow()函数 调用grow(int minCapacity)函数,其中传参的值,是目前需要的最小空间值.

  2. 在经过newCapacity的计算之后将 新的对象数组的值,copy到elementData中.由此便完成了第一次扩容.

  3. 最小值更新minCapacity为11

private Object[] grow(int minCapacity) {return elementData = Arrays.copyOf(elementData,newCapacity(minCapacity));
}
private Object[] grow() {return grow(size + 1);
}

进入newCapacity(minCapacity)可以看到如下源码:

  1. oldCapacity旧容量的值设置为对象数组的长度,newCapacity新容量的值设置为老容量+老容量的一次右移运算.

  2. 操作了半个小时结果发现newCapacity为0,然后进入if循环,发现目前的elementData一点没动,其地址还是最初的时候赋值的DEFAULTCAPACITY_EMPTY_ELEMENTDATA.

  3. 在默认容量DEFAULT_CAPACITY=10和最小容量minCapacity=1之间选择一个最大值,也就是10.作为返回值.

  4. newCapacity在经过右移运算后为15 . 然后执行就以15为最新的扩容值为准 返回.

private static final int DEFAULT_CAPACITY = 10;
private int newCapacity(int minCapacity) {// overflow-conscious codeint oldCapacity = elementData.length;int newCapacity = oldCapacity + (oldCapacity >> 1);if (newCapacity - minCapacity <= 0) {if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)return Math.max(DEFAULT_CAPACITY, minCapacity);if (minCapacity < 0) // overflowthrow new OutOfMemoryError();return minCapacity;}return (newCapacity - MAX_ARRAY_SIZE <= 0)? newCapacity: hugeCapacity(minCapacity);
}


Vector的源码和ArrayList对比只有一点的不同, 那就是Vector在添加元素的时候加了线程锁, 是线程安全的.

public synchronized boolean add(E e) {modCount++;add(e, elementData, elementCount);return true;
}

总结: 其实就是扩容的操作解读, 赋值很简单. 而且源码的条例就是比我们自己写的好得多.

转载于:https://www.cnblogs.com/A-FM/p/10970743.html

JDK12下的ArrayList源码解读 与 Vector的对比相关推荐

  1. ArrayList源码解读

    ArrayList源码解读 底层数据结构 ArrayList是在底层维护了一个elementData数组,添加了自动扩容等功能,最终形成了一个动态数组. 基本属性 // 初始化大小 private s ...

  2. java1.8 indexes_java1.8源码之ArrayList源码解读

    文章目录 一.ArrayList概述1.1 ArrayList简介1.2 ArrayList数据结构 二.ArrayList源码分析2.1 ArrayList继承结构和层次关系2.2 类的属性2.3 ...

  3. Java Review - ArrayList 源码解读

    文章目录 概述 方法的执行效率 源码剖析 底层数据结构 -数组 构造函数 自动扩容机制 set() get add()/addAll() remove() trimToSize() indexOf() ...

  4. 【集合详解】ArrayList源码解读之动态扩容

    ArrayList 概述 ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长. ArrayList不是线程安全的,只能用在单线程环境下. 实现了Serializable接口,因此它支 ...

  5. Java Review - PriorityQueue源码解读

    文章目录 Pre PriorityQueue 概述 PriorityQueue 继承关系 PriorityQueue通过用数组表示的小顶堆实现 时间复杂度 构造函数 方法 add()和offer() ...

  6. Java Review - Queue和Stack 源码解读

    文章目录 Pre 概述 Queue Deque ArrayDeque 一览 构造函数 属性 方法 addFirst() addLast() pollFirst() pollLast() peekFir ...

  7. Java Review - LinkedList源码解读

    文章目录 Pre 概述 底层数据结构-双向链表 源码解析 构造函数 方法源码分析 getFirst() getLast() remove相关方法 remove(e) remove(index) rem ...

  8. ArrayList源码详细解析(一)

    Java ArrayList源码解析(基于JDK 12,对比JDK 8) 自从接触到ArrayList以来,一直觉得很方便,但是从来没有系统.全面的学习了解过ArraryList的实现原理.最近学习了 ...

  9. Java 集合系列(2): ArrayList源码深入解析和使用示例

    戳上面的蓝字关注我们哦! 精彩内容 精选java等全套视频教程 精选java电子图书 大数据视频教程精选 java项目练习精选 概要 上一章,我们学习了Collection的架构.这一章开始,我们对C ...

最新文章

  1. iOS开发笔记(十七):持久化方案之 NSUserDefaults
  2. qstring如何初始化_QString介绍
  3. tinyhttpd-0.1.0_hacking
  4. 安卓实训项目:基于储存卡音乐播放器实训报告4.0
  5. padding-bottom属性的作用
  6. Stern-Brocot Tree
  7. [html] html5中的meta标签http-equiv属性有什么作用?
  8. JME3中级手册一API特征映射1
  9. react开发_我如何在#100DaysOfCode挑战期间找到React开发人员的工作
  10. 透露一个未来3到5年的巨大商机
  11. win10 基础之上安装 Linux-Manjaro-Deepin 连夜采坑,快速整理下
  12. python如何测试rabbit_Python如何检测到我的RabbitMQ密码失败?
  13. txt文档下载另存为解决
  14. linux brctl
  15. 两步搞定经验模态分解与离散小波变换
  16. SpringBootJ2EE相关介绍
  17. day_05 运算符 if和while的使用
  18. 【快代理API】获取隧道代理IP
  19. android : 小米手机 打开开发者 选项 PC 端 安装 apk
  20. CAD闪退的解决方法

热门文章

  1. win32应用程序_不是有效的win32应用程序怎么解决
  2. mysql5_pn卸载_windows mySql(5.7.30) 卸载及重装
  3. tomcat出现5个using_出现急性心梗,要当心5个并发症,一个都不好惹!
  4. 翟萍python程序设计_Python程序设计(高等学校计算机教育规划教材)
  5. java qq音乐接口 api,QQ音乐解析API接口更新:支持HQ,ape,flac无损音质,缓存功能
  6. html5 呼吸灯效果,jQuery仿地铁线路指示灯效果
  7. 微信开发之自动回复图文消息
  8. 你连原理都还没弄明白?快来瞧瞧这份Spring面试小抄
  9. Eclipse的正确安装使用姿势
  10. python【蓝桥杯vip练习题库】ALGO-142 P1103(复数运算)