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

2017-02-25 20:35:14 +08:00
 yang2yang
    /**
     * 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 啊?

3364 次点击
所在节点    Java
10 条回复
param
2017-02-25 21:04:26 +08:00
我仿佛又听到有人在背后偷偷 @我
LaudOak
2017-02-25 21:10:14 +08:00
@param 蛤蛤
yang2yang
2017-02-25 21:40:31 +08:00
@param 为啥。。
snnn
2017-02-25 21:43:08 +08:00
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
2017-02-26 10:04:04 +08:00
@yang2yang #3 当让是因为他用户名了,你看看 JAVA 注释……
mikulch
2017-02-26 12:06:16 +08:00
建议楼主不要纠结这些东西
编程是用来解决问题滴。
yang2yang
2017-02-26 13:25:49 +08:00
@czk1997 额,好吧。。

@mikulch 我知道啊,但是还是想要深入理解一下
yang2yang
2017-02-28 16:22:03 +08:00
@snnn 谢谢,拜读好久,很有帮助。
log4geek
2017-03-23 09:39:12 +08:00
zhgg0
2019-09-18 15:16:57 +08:00
楼主后来弄懂了这个问题不?求解释

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/343150

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX