java 中的 int 数组在内存中存储为 32 位值的块。Integer 对象数组是如何存储的?IE。

int[] vs. Integer[]

我想象 Integer 数组中的每个元素都是对 Integer 对象的引用,并且 Integer 对象具有对象存储开销,就像任何其他对象一样。

然而,我希望 JVM 在幕后能发挥一些神奇的聪明才智,因为整数是不可变的,并且就像整数数组一样存储它。

我的希望是不是太天真了?在性能至关重要的应用程序中,整数数组是否比 int 数组慢得多?

有帮助吗?

解决方案

据我所知,没有任何虚拟机会像 int[] 数组那样存储 Integer[] 数组,原因如下:

  1. 可以有 无效的 数组中的整数对象,并且在 int 数组中没有剩余的位来指示这一点。不过,VM 可以将每个数组槽的 1 位信息存储在隐藏的位数组中。
  2. 您可以同步整数数组的元素。作为第一点,这一点更难克服,因为您必须为每个数组槽存储一个监视器对象。
  3. Integer[] 的元素可以进行同一性比较。例如,您可以通过以下方式创建两个值为 1 的 Integer 对象 新的 并将它们存储在不同的数组槽中,稍后检索它们并通过 == 进行比较。这肯定会导致错误,因此您必须将此信息存储在某个地方。或者,您在某处保留对 Integer 对象之一的引用,并使用它进行比较,并且您必须确保 == 比较之一为假,另一为真。这意味着对象身份的整个概念对于 优化 整数数组。
  4. 您可以将 Integer[] 转换为例如Object[] 并将其传递给只需要一个 Object[] 的方法。这意味着处理 Object[] 的所有代码现在也必须能够处理特殊的 Integer[] 对象,从而使其速度更慢且更大。

考虑到所有这些,可能可以制作一个特殊的 Integer[] ,与 幼稚的 实现,但额外的复杂性可能会影响许多其他代码,最终使其变慢。

使用 Integer[] 代替 int[] 的空间和时间开销可能会非常大。在典型的 32 位 VM 上,Integer 对象将消耗 16 个字节(8 个字节用于对象头,4 个字节用于有效负载,4 个附加字节用于对齐),而 Integer[] 使用与 int[] 一样多的空间。在 64 位 VM 中(使用 64 位指针,但情况并非总是如此),Integer 对象将消耗 24 个字节(16 个用于标头,4 个用于有效负载,4 个用于对齐)。此外,Integer[] 中的槽将使用 8 个字节,而不是 int[] 中的 4 个字节。这意味着您预计的开销为 16 至 28 每个插槽字节,这是 4 到 7 的因数 与普通 int 数组相比。

性能开销也可能很大,主要有两个原因:

  1. 由于使用了更多内存,因此对内存子系统施加了更大的压力,在 Integer[] 的情况下更有可能发生缓存未命中。例如,如果您以线性方式遍历 int[] 的内容,则缓存将在您需要时已获取大部分条目(因为布局也是线性的)。但对于 Integer 数组,Integer 对象本身可能随机分散在堆中,使得缓存很难猜测下一个内存引用将指向哪里。
  2. 垃圾回收必须做更多的工作,因为使用了额外的内存,并且它必须单独扫描和移动每个 Integer 对象,而在 int[] 的情况下,它只是一个对象,并且对象的内容不会必须被扫描(它们不包含对其他对象的引用)。

总而言之,在性能关键的工作中使用 int[] 比在当前虚拟机中使用 Integer 数组要快得多,内存效率也高,而且在不久的将来这种情况不太可能发生太大变化。

其他提示

约翰·罗斯致力于 固定数 在JVM中解决这个问题。

我认为你的希望太天真了。具体来说,它需要处理 Integer 可能为 null 而 int 不能为 null 的问题。仅此一点就足以存储对象指针。

也就是说,实际的对象指针将指向一个不可变的 int 实例,特别是对于整数的选择子集。

它不会慢很多,但是因为 Integer[] 必须接受“null”作为条目,而 int[] 则不必接受,所以即使 Integer[] 由一个整数[]。

因此,如果每一点性能都很重要,那么用户 int[]

Integer 可以为 null,而 int 不能为 null 的原因是,Integer 是一个成熟的 Java 对象,具有其中包含的所有开销。这很有价值,因为你可以写

Integer foo = new Integer();
foo = null; 

这很好地表明 foo 将会有一个值,但它还没有。

另一个区别是 int 不执行溢出计算。例如,

int bar = Integer.MAX_VALUE;
bar++;

会愉快地增加 bar 并且你最终会得到一个非常负的数字,这可能不是你最初想要的。

foo = Integer.MAX_VALUE;
foo++;

会抱怨,我认为这是更好的行为。

最后一点是,Integer 作为 Java 对象,会带来对象的空间开销。我认为其他人可能需要在这里插话,但我相信每个对象消耗 12 个字节的开销,然后是数据存储本身的空间。如果您追求性能和空间,我想知道 Integer 是否是正确的解决方案。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top