引用ArrayList中的元素,后来移动



假定以下代码:

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());

之后的销售仍然正确地引用了Alist [500],即使阵列列表可能在第二个循环中多次重新分配了其数据。这个假设不正确吗?

我的理论是,要么不是释放内存肛门元素引用,而是要指向当前的alist数据,或者在生长数组时会更新参考元素。然而,这两种理论都具有很差的空间/时间绩效含义,因此我认为它们不太可能。

编辑:

我误解了数组如何存储元素,我以为它们直接存储它们,但实际上它们存储了参考文献,这意味着Anelement和Alist [500]都指向堆上的某个对象,解决了我未能理解的问题!<<<<<</p>

当内部存储ArrayList的元素的数组变得完整,新,较大的数组正在创建,并且上一个数组中的所有元素都在同一索引上复制到新的元素,现在在那里是新元素的空间。垃圾收集器将摆脱以前的,不需要更多的数组。

您可能希望在此处查看ArrayList的实现守则,以查看其在"引擎盖下"的工作方式。

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

请注意,ArrayList实际上不像数组(例如A S的数组是A[](,并且它不是固定尺寸的集合-ArrayList在添加或删除元素时会更改其大小-e。G。如果您以索引0(aList.remove(0);(删除元素,则存储在索引1000的元素现在存储在索引999,ArrayList的大小也从1000变为999。

如果您想知道阵列列表在内部的工作方式,只需查看您可以在线找到的来源,例如:http://grepcode.com/file/repository.grepcode.com/java/root/jdk/jdk/openjdk/6-b14/java/java/java/util/arraylist.java

在这里,您可以清楚地看到Object[]是内部使用的,该CC_12在被认为是Neccessary时调整到int newCapacity = (oldCapacity * 3)/2 + 1;大小。

只要您在背面添加一些东西,索引保持不变。如果您是否在中间插入某些元素的所有索引。

不是Java,而是给定JVM的实现细节。您可以在此处阅读一些内容:https://www.artima.com/insidejvm/ed2/jvm6.html,因此有有关JVM内部的完整书籍。
一种简单的方法是拥有对象图,因此您首先参考该映射,然后找到实际对象的当前位置。然后,将实际对象移动到周围很容易,因为其地址存储在单个副本中,在该地图中。
可以说这很慢,直接存储地址,并且没有在地图中查找对象的额外步骤。这样,将对象移动到周围将需要更多的工作,尽管仍然可以更新所有指针(因为原始指针不会出现在语言级别上,暂时施放到数字或在某些随机数组中存储,并且类似的魔术无法做到危害在这里,您总是可以跟踪指向您要移动的对象的指针(。

最新更新