【问题标题】:Reference to element in ArrayList which is later moved对 ArrayList 中元素的引用,该元素稍后被移动
【发布时间】:2018-08-03 12:27:54
【问题描述】:

假设以下代码:

ArrayList<A> aList = new ArrayList<>();
for(int i = 0; i < 1000; ++i) 
    aList.add(new A());
A anElement = aList.get(500);
for(int i = 0; i < 100000; ++i) 
    aList.add(new A());

之后 anElement 仍然正确引用 aList[500],即使 ArrayList 可能在第二个 for 循环期间多次重新分配其数据。这个假设是否不正确,如果不正确,Java 如何设法让 anElement 仍然指向内存中的正确数据?

我的理论是,要么不是释放内存 anElement 引用,而是内存现在指向当前的 aList 数据,或者当数组增长时更新 anElement 的引用。然而,这两种理论都具有非常糟糕的空间/时间性能影响,所以我认为它们不太可能。

编辑:

我误解了数组是如何存储元素的,我以为它们直接存储它们,但实际上它们存储引用,这意味着 anElement 和 aList[500] 都指向堆上的某个对象,解决了我无法理解的问题!

【问题讨论】:

  • 将元素移动到哪里?

标签: java arraylist


【解决方案1】:

这不是 Java,而是给定 JVM 的实现细节。你可以在这里阅读一些东西:例如https://www.artima.com/insidejvm/ed2/jvm6.html,所以有完整的关于 JVM 内部的书籍。
一个简单的方法是拥有一张对象地图,因此您首先参考该地图,然后找到实际对象的当前位置。然后移动实际对象很简单,因为它的地址存储在该地图中的单个副本中。
可以说这很慢并且直接存储地址,而无需在地图中查找对象的额外步骤。这种方式移动对象将需要更多的工作,虽然仍然可能,只是所有指针都必须更新(因为原始指针不会出现在语言级别,临时转换为数字或存储在一些随机数组中,类似的魔法不能做伤害在这里,您始终可以跟踪某物是否是指向您正在移动的对象的指针)。

【讨论】:

    【解决方案2】:

    当内部存储ArrayList 元素的数组变满时,将创建新的更大的数组,并将前一个数组中的所有元素复制到相同索引处的新数组,现在有一个空间用于新元素.垃圾收集器将摆脱以前的、不再需要的数组。

    您可能想查看ArrayList here 的实现代码,以了解其“幕后”工作原理的详细信息。

    代码中的第二个循环,在第 1000 个元素之后添加了下一个 100000 个元素,所以现在您在 aList 中有 101000 个元素,前 1000 个元素没有移动到任何地方。使用get() 方法,您只能读取该元素,不会从该ArrayList 中移动或删除任何内容。

    请注意,ArrayList 并不像数组那样工作(例如,As 的数组是 A[])而且它不是一个固定大小的集合 - ArrayList 在添加或删除元素时会改变它的大小 - e . G。如果删除索引 0 (aList.remove(0);) 处的元素,则存储在索引 1000 处的元素现在存储在索引 999 处,ArrayList 的大小也会从 1000 变为 999。

    【讨论】:

    • 我认为我的逻辑错误在于底层数组包含元素的实际数据(如在 C 中),而实际上它包含对独立存储的对象的引用?跨度>
    • @Barikami 希望这些答案对您有所帮助:stackoverflow.com/questions/5564423/…
    【解决方案3】:

    如果您想了解 ArrayList 内部的工作原理,只需查看您可以在网上找到的资源,例如这里: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/ArrayList.java

    在这里您可以清楚地看到内部使用了Object[],并在认为必要时将其大小调整为int newCapacity = (oldCapacity * 3)/2 + 1;

    只要您在后面添加一些内容,索引就会保持不变。如果你在中间插入一些东西,后面的所有元素索引都会加一。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-02-27
      • 1970-01-01
      • 1970-01-01
      • 2014-05-06
      • 1970-01-01
      • 2014-03-19
      • 1970-01-01
      相关资源
      最近更新 更多