• 新年快乐,干货储备充足了吗?--- ArrayList解析


           今天大年初一,大家都在忙着拜年吧!在这里祝大家新年快乐,鼠年大吉!!!除了拜年,相信也有很多人正在储备干货,为了假期之后的金三银四做准备。当然我也没有闲着,在家里忙着过年的空闲时间里面,多学习新的知识,打一场轰轰烈烈的有准备的仗。

           在学习的过程中,我也在不断地思考,我们为什么要学习?学习能给我们带来什么?慢慢的我也想通了,想明白了。其实在学习的过程中,我们就像是在一篇汪洋的大海中遨游,刚开始我们接触技术的时候,犹如在海面上面,看到了海上美丽的风景,我们为之感叹世界的奇妙与鬼斧神工。我们一点点的了解这个世界,当你对周围的一切都已经看遍了的时候,我们又不希望止步于此,希望向更远的地方前行,看不一样的风景。于是你就不断的学习新的知识,在项目中用我们所学的知识去实践。我们在这个海洋上面用知识所造就的小船、游艇遨游,这些我们知识停留在知识的表面,学会怎么使用它们,知其然不知所以然而已。当你的好奇心不满足于此的时候,不满足海面的风景的时候,想要学习底层知识的时候。你就会放弃你的小船、游艇,纵身跳入无边无际的海洋里面去,一点一点的向海底进军,可能开始的时候我们下游的缓慢,难忍的无法呼吸等重重困难,但是当你到达海底的那一瞬间,你就会爱上这个海底世界,就会发觉前面的努力都是值得的,为了这一刻。这就是我学习的感悟。好了,闲聊了这么多的,我还是讲讲最近的收获。

    下面是JAVA技术人员的干货时间:

    (1)ArrayList的最大容量为(Integer.MAX_VALUE - 8),但容量超过了MAX_ARRAY_SIZE的时候再扩容为Integer.MAX_VALUE大小,我们可能一直以为ArrayList没有最大容量限制,后来看了源码jdk8才知道有一个数组最大容量限制常量,尝试分配更大的阵列可能会导致 OutOfMemoryError异常。源码如下:

       /**
         * 要分配的最大数组大小。 一些虚拟机在数组中保留一些标题字。
         * 但是扩容容量大小超过了MAX_ARRAY_SIZE值的时候会调用hugeCapacity方法,
         * 方法里面满足条件就会扩容为Integer.MAX_VALUE的值
         * 尝试分配更大的阵列可能会导致 OutOfMemoryError:请求的阵列大小超出VM限制
         */
        private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    
        // 超过了MAX_ARRAY_SIZE的大小的时候,扩容为Integer.MAX_VALUE的大小
        private static int hugeCapacity(int minCapacity) {
            // 参数小于0,抛出OutOfMemoryError异常
            if (minCapacity < 0) // overflow
                throw new OutOfMemoryError();
            // 容量大于MAX_ARRAY_SIZE的时候,扩容为Integer.MAX_VALUE,否则为MAX_ARRAY_SIZE
            return (minCapacity > MAX_ARRAY_SIZE) ?
                Integer.MAX_VALUE :
                MAX_ARRAY_SIZE;
        }

    (2)ArrayList的默认容器大小为10,源码如下:

    // 默认容器大小
    private static final int DEFAULT_CAPACITY = 10;
     

    (3)ArrayList使用构造函数进行初始化的时候

    • 未传容量大小参数是使用ArrayList默认大小,初始对象为共享变量DEFAULTCAPACITY_EMPTY_ELEMENTDATA
    • 传容量大小参数的时候,容器大小参数为0则初始对象为共享变量EMPTY_ELEMENTDATA,不为0的时候初始化对象数组

    为什么会用两种不同的共享变量呢? 因为为了区分两种情况,使用了默认容量大小初始化和未使用默认容量初始化,如果初始对象和DEFAULTCAPACITY_EMPTY_ELEMENTDATA引用地址是一样的话,说明使用默认容量大小10,就会设置size=10.如果不区分开怎么知道你使用的size是默认的还不是默认的

    源码如下:

     /**
         * 用于空实例的共享空数组实例
         */
        private static final Object[] EMPTY_ELEMENTDATA = {};
        
        /**
         * 共享的空数组实例,用于默认大小的空实例。我们将其与EMPTY_ELEMENTDATA区别开来,
         * 以知道添加第一个元素时需要扩容多少。
         */
        private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
        
        // 无参构造函数,构造一个初始容量为10的空列表
        public ArrayList() {
            this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
        }
        
        /**
         * 有参构造函数,下面的注释解析了第四点知识点
         *
         * 初始化的时候只是初始化了对象数组,没有初始化size大小。
         * set()方法插入元素的时候,会进行校验就会抛出异常
         */
        public ArrayList(int initialCapacity) {
            if (initialCapacity > 0) {
                this.elementData = new Object[initialCapacity];
            } else if (initialCapacity == 0) {
                this.elementData = EMPTY_ELEMENTDATA;
            } else {
                throw new IllegalArgumentException("Illegal Capacity: "+
                                                   initialCapacity);
            }
        }
     

    (4)ArrayList初始化的时候即使设置了初始容量大小,但是不会设置size的值, set会有一个index和size大小校验,如果index大于size会抛出异常,只能通过add方法改变size的值,初始容量只是改变了在初始数组对象加了一个没有设置容量大小,但会设置一个默认的EMPTY_ELEMENTDATA或者DEFAULTCAPACITY_EMPTY_ELEMENTDATA空对象数组。 源码如下:

       public E set(int index, E element) {
            // 下标检查
            rangeCheck(index);
    
            // index下标位置上的原元素
            E oldValue = elementData(index);
            elementData[index] = element;
            return oldValue;
        }
        
        // 下标检查
         private void rangeCheck(int index) {
            if (index >= size)
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }

         注意:size只有在ArrayList调用了add方法的时候才会增加size变量的值,rangeCheck方法校验size和index大小校验,index不能大于size,否则会抛出异常IndexOutOfBoundsException

  • 相关阅读:
    阶段3 1.Mybatis_10.JNDI扩展知识_2 补充-JNDI搭建maven的war工程
    阶段3 1.Mybatis_10.JNDI扩展知识_1 补充-JNDI概述和原理
    阶段3 1.Mybatis_09.Mybatis的多表操作_9 mybatis多对多操作-查询用户获取用户所包含的角色信息
    阶段3 1.Mybatis_09.Mybatis的多表操作_8 mybatis多对多操作-查询角色获取角色下所属用户信息
    阶段3 1.Mybatis_09.Mybatis的多表操作_7 mybatis多对多准备角色表的实体类和映射配置
    阶段3 1.Mybatis_09.Mybatis的多表操作_6 分析mybatis多对多的步骤并搭建环境
    阶段3 1.Mybatis_09.Mybatis的多表操作_5 完成user的一对多查询操作
    阶段3 1.Mybatis_09.Mybatis的多表操作_4 完成account一对一操作-建立实体类关系的方式
    inline函数不能在for循环中使用的原因
    Linux 内核死锁
  • 原文地址:https://www.cnblogs.com/javJoker/p/12236709.html
Copyright © 2020-2023  润新知