博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JDK12下的ArrayList源码解读 与 Vector的对比
阅读量:6347 次
发布时间:2019-06-22

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

ArrayList源码阅读.

//测试代码实现如下 private static void arrayList() {        ArrayList
list = new ArrayList
(); 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 accessprivate 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 code    int 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) // overflow            throw 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

你可能感兴趣的文章
RHEL系列网络配置2015083101
查看>>
c# 基本值类型及其默认值
查看>>
服务器端解决JS跨域调用问题
查看>>
迁移至个人blog
查看>>
MySql中添加用户,新建数据库,用户授权,删除用户,修改密码
查看>>
雨巷-戴望舒
查看>>
OpenCms创建网站过程图解——献给OpenCms的初学者们
查看>>
C++ 异常处理机制的实现
查看>>
Freebsd的ports命令
查看>>
分布式系统---幂等性设计
查看>>
【转】时钟周期,机器周期,指令周期的区别
查看>>
MYSQL 更新时间自己主动同步与创建时间默认值共存问题
查看>>
android 屏幕适配
查看>>
Android Activity的4种启动模式
查看>>
leetcode第一刷_Minimum Depth of Binary Tree
查看>>
pm2-webshell —— 基于浏览器的终端控制台
查看>>
Mysql基准测试
查看>>
Session 撰改演示
查看>>
【转】python3 发邮件实例(包括:文本、html、图片、附件、SSL、群邮件)
查看>>
事务隔离级别(图文详解)
查看>>