yang2yang
V2EX  ›  Java

Java 的 ArrayList 中有点问题求指点~~~

  •  
  •   yang2yang ·
    yang2yang · Feb 25, 2017 · 4512 views
    This topic created in 3544 days ago, the information mentioned may be changed or developed.
        /**
         * The maximum size of array to allocate.
         * Some VMs reserve some header words in an array.
         * Attempts to allocate larger arrays may result in
         * OutOfMemoryError: Requested array size exceeds VM limit
         */
        private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
        
        
            /**
         * Increases the capacity to ensure that it can hold at least the
         * number of elements specified by the minimum capacity argument.
         *
         * @param minCapacity the desired minimum capacity
         */
        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);
        }
    
        private static int hugeCapacity(int minCapacity) {
            if (minCapacity < 0) // overflow
                throw new OutOfMemoryError();
            return (minCapacity > MAX_ARRAY_SIZE) ?
                Integer.MAX_VALUE :
                MAX_ARRAY_SIZE;
        }
    

    为什么这里 MAX_ARRAY_SIZE 会写成是 Integer.MAX_VALUE - 8?

    注释上面说是因为 header words in an array?如果这个 header words 是说下面 so 说的情况,会多 8 个字节的话?

    so上面说是因为数组对象需要多存一个 8 个字节的 size 大小,所以需要减 8?但是仅仅是在 Integer.MAX_VALUE-8 就可以省下不止 8 字节的空间把? 8 个 int 型,每个 4 个字节,应该不是可以省下 32 个字节?那不是应该-2 ?

    知乎上面说只是为了避免一些机器内存溢出....所以说这个 -8 是为了减少出错的几率?只是为了减少出错的几率,所以选择少分配一些?

    但是我看hugeCapacity函数,当 minCapacity > MAX_ARRAY_SIZE ,最后还是选择了 Integer.MAX_VALUE,来开辟数组,那么所以最大的情况下还是选择了 Integer.MAX_VALUE ?那么 MAX_ARRAY_SIZE 其实没有被使用到?

    还有 hugeCapacity 函数如果抛出 OutOfMemoryError 的话,因为 minCapacity = size+1,所以 size 原来是 Integer.MAX_VALUE ?所以还是可以会开辟出来最大的长度是 Integer.MAX_VALUE ?那么是不是 MAX_ARRAY_SIZE 其实并没有什么意义?

    其实就想问源码中 MAX_VALUE 是出于一个什么目的来进行定义的?具体是怎么使用的?为什么减 8 啊?

    10 replies  •  2019-09-18 15:16:57 +08:00
    param
    param
    Feb 25, 2017 via Android
    1
    我仿佛又听到有人在背后偷偷 @我
    LaudOak
    LaudOak
    Feb 25, 2017 via Android
    2
    @param 蛤蛤
    yang2yang
    yang2yang
    OP
    Feb 25, 2017
    3
    @param 为啥。。
    snnn
    snnn
    Feb 25, 2017❤️1
    4
    oldCapacity :是你当前的长度
    minCapacity: 是你至少需要多长
    newCapacity :是你将来的长度。
    显然 oldCapacity<=minCapacity<=newCapacity<=Integer.MAX_VALUE
    一个基本原则:要让 newCapacity 尽可能的满足 minCapacity 。如果不能满足,一定要抛异常。
    什么时候 newCapacity >= MAX_ARRAY_SIZE? 答: oldCapacity + (oldCapacity >> 1) >= MAX_ARRAY_SIZE
    在这种情况下,为了防止计算溢出,干脆就让 newCapacity = MAX_ARRAY_SIZE
    但是万一这样不够呢?
    分两种情况:如果超出了 max int ,就抛异常。否则比如 minCapacity=Integer.MAX_VALUE - 2 ,那么就让它等于 Integer.MAX_VALUE
    czk1997
    czk1997
    Feb 26, 2017
    5
    @yang2yang #3 当让是因为他用户名了,你看看 JAVA 注释……
    mikulch
    mikulch
    Feb 26, 2017
    6
    建议楼主不要纠结这些东西
    编程是用来解决问题滴。
    yang2yang
    yang2yang
    OP
    Feb 26, 2017 via Android
    7
    @czk1997 额,好吧。。

    @mikulch 我知道啊,但是还是想要深入理解一下
    yang2yang
    yang2yang
    OP
    Feb 28, 2017
    8
    @snnn 谢谢,拜读好久,很有帮助。
    log4geek
    log4geek
    Mar 23, 2017
    9
    zhgg0
    zhgg0
    Sep 18, 2019
    10
    楼主后来弄懂了这个问题不?求解释
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   960 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 22:23 · PVG 06:23 · LAX 14:23 · JFK 17:23
    ♥ Do have faith in what you're doing.