Java 中的整数数组作为 32 位值块存储在内存中。如何存储 Integer 对象数组?IE
int[] vs. Integer[]
我想 Integer 数组中的每个元素都是对 Integer 对象的引用,并且 Integer 对象具有对象存储开销,就像任何其他对象一样。
然而,我希望 JVM 在后台做一些神奇的聪明,因为整数是不可变的,并且像整数数组一样存储它。
我的希望是不是太天真了?在每最后一盎司的性能都很重要的应用程序中,整数数组是否比 int 数组慢得多?
我所知道的任何 VM 都不会像 int[] 数组那样存储 Integer[] 数组,原因如下:
考虑到所有这些,可能有可能制作一个特殊的 Integer[] 与幼稚的实现相比节省一些空间,但额外的复杂性可能会影响许多其他代码,最终使其变慢。
使用 Integer[] 而不是 int[] 的开销在空间和时间上可能会很大。在典型的 32 位 VM 上,一个 Integer 对象将消耗 16 个字节(8 个字节用于对象标头,4 个字节用于负载,4 个额外字节用于对齐),而 Integer[] 使用与 int[] 一样多的空间。在 64 位 VM(使用 64 位指针,并非总是如此)中,整数对象将消耗 24 个字节(16 个用于标头,4 个用于有效负载,4 个用于对齐)。此外,Integer[] 中的插槽将使用 8 个字节而不是 int[] 中的 4 个字节。这意味着您可以预期每个插槽的开销为16 到 28个字节,与普通 int 数组相比,这是4 到 7 倍。
性能开销也很重要,主要有两个原因:
总而言之,在性能关键的工作中使用 int[] 将比在当前 VM 中使用 Integer 数组更快且内存效率更高,并且在不久的将来这不太可能发生太大变化。
John Rose在 JVM 中使用fixnums来解决这个问题。
我认为你的希望太天真了。具体来说,它需要处理 Integer 可能为 null 而 int 不能为 null 的问题。仅此一项就足以存储对象指针。
也就是说,实际的对象指针将指向一个不可变的 int 实例,特别是对于整数的选择子集。
它不会慢很多,但是因为 Integer[] 必须接受“null”作为条目而 int[] 不必接受,所以即使 Integer[] 由整数 []。
因此,如果每一盎司的性能都很重要,用户 int[]
Integer 可以为 null 而 int 不能为空的原因是,Integer 是一个成熟的 Java 对象,其中包含所有开销。这是有价值的,因为你可以写
Integer foo = new Integer();
foo = null;
这很适合说 foo 将具有价值,但还没有。
另一个区别是不int
执行溢出计算。例如,
int bar = Integer.MAX_VALUE;
bar++;
将愉快地增加 bar 并且你最终得到一个非常负数,这可能不是你最初想要的。
foo = Integer.MAX_VALUE;
foo++;
会抱怨,我认为这是更好的行为。
最后一点是,作为 Java 对象的 Integer 带有对象的空间开销。我认为其他人可能需要在这里插话,但我相信每个对象都会消耗 12 个字节的开销,然后是数据存储本身的空间。如果您追求性能和空间,我想知道 Integer 是否是正确的解决方案。