zoukankan      html  css  js  c++  java
  • ArrayList原理解析

    ArrayList扩容机制为什么是1.5倍+1

    这里是自己参考jdk [version "1.8.0_144"] ,也是目前正在使用的

    • 类实现
    public class ArrayList<E> extends AbstractList<E>
            implements List<E>, RandomAccess, Cloneable, java.io.Serializable
    
    • 重要属性
    /**
         * 默认初始容量
         */
        private static final int DEFAULT_CAPACITY = 10;
    
        /**
         * 用于空实例的共享空数组实例.
         */
        private static final Object[] EMPTY_ELEMENTDATA = {};
    
        /**
         * 用于默认大小的空实例的共享空数组实例,ArrayList的容量是此数组缓冲区的长度
         */
        private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    
        /**
         * 存储ArrayList元素的数组缓冲区.
         */
        transient Object[] elementData; // 非私有,以简化嵌套类访问
    
        /**
         * ArrayList的大小(它包含的元素数).
         */
        private int size;
        
        /**
         * 结构修改的次数
         */
        protected transient int modCount = 0;
    

    Java中transient关键字的作用,简单地说,就是让某些被修饰的成员属性变量不被序列化

    1.基本属性概念

    size是数据的个数!elementData.length是elementData的c长度(包含被元素占用的空间和预留的空间)

    public boolean add(E e) {
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            elementData[size++] = e;
            return true;
        }
    

    将现在的长度size加一后,传进ensureCapacityInternal里面

    2.初始化

    DEFAULTCAPACITY_EMPTY_ELEMENTDATA是空数组,表示现在ArrayList是空的

    private void ensureCapacityInternal(int minCapacity) {
            if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
                minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
            }
    
            ensureExplicitCapacity(minCapacity);
        }
    

    ensureCapacityInternal中首先是判断现在的ArrayList是不是空的,如果是空的,minCapacity就取默认的容量和传入的参数minCapacity中的大值
    然后调用ensureExplicitCapacity方法

    3.fail fast机制

    modCount是fail fast机制,在jdk1.6之前都是有volatile来修饰的,尽可能的让并发访问非安全的集合对象时尽快的失败抛出异常,让程序员修改代码

    private void ensureExplicitCapacity(int minCapacity) {
            modCount++;
    
            // overflow-conscious code
            if (minCapacity - elementData.length > 0)
                grow(minCapacity);
    }
    

    在jdk1.7中去掉了volatile修饰,因为感觉没有必要为非线程安全集合浪费效率,在jdk1.5开始就提供了线程安全的集合类,在多线程环境下就应该使用线程安全的集合。
    接着看,如果minCapacity的值大于add数据之前的大小,就调用grow方法,进行扩容,否则什么也不做

    4.扩容的原理?

    注意:这里传过来的minCapcatiy的值是size+1,能够实现grow方法调用就肯定是(size+1)>elementData.length的情况,所以size就是初始最大容量或上一次扩容后达到的最大容量,所以才会进行扩容

    private void grow(int minCapacity) {
            // overflow-conscious code
            int oldCapacity = elementData.length;
            int newCapacity = oldCapacity + (oldCapacity >> 1);
            if (newCapacity - minCapacity < 0)
                newCapacity = 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);
        }
    

    newCapacity=oldCapacity+(oldCapacity>>1),这里就是扩容大小确定的地方,相当于新的最大容量是 size+1;size=1+0.5
    相当于原来的1.5倍然后加1


    • 参考文章

      https://blog.csdn.net/JustForWorld/article/details/83119703
  • 相关阅读:
    要改变静态文本框的值,必须设置静态文本框控件的样式中(Notify通知)勾选
    MFC对话框中的编辑控件的7种操作方式
    孙鑫C++视频教程 rmvb格式 全20CD完整版
    Windows server2008 下 PowerShell对.NET3.5静默安装
    MFC关机函数
    PDI-KETTLE-2:KETTLE安装,环境变量配置,开发准备
    KETTLE常见问题记录第一篇【安装,资源库,数据库】
    日常问题解决记录一:远程桌面进程如果关闭了怎么呼出?
    KETTLE调度第二篇:把Jenkins调度Web启动设置为后台执行
    PDI-KETTLE-1:使用KETTLE如何设计一个作业-以数据库迁移为例
  • 原文地址:https://www.cnblogs.com/ringbug/p/11343553.html
Copyright © 2011-2022 走看看