Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/345.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 对ArrayList中稍后移动的元素的引用_Java_Arraylist - Fatal编程技术网

Java 对ArrayList中稍后移动的元素的引用

Java 对ArrayList中稍后移动的元素的引用,java,arraylist,Java,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()); ArrayList aList=new ArrayList(); 对于(int i

假设以下代码:

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());
ArrayList aList=new ArrayList();
对于(int i=0;i<1000;++i)
aList.add(新的A());
A元素=aList.get(500);
对于(int i=0;i<100000;++i)
aList.add(新的A());
之后,一个元素仍然正确地引用了aList[500],即使ArrayList可能在第二个for循环中多次重新分配了它的数据。这个假设是否不正确?如果不正确,Java如何使元素仍然指向内存中的正确数据

我的理论是,不是释放内存元素引用,而是内存现在指向当前的数据,或者在增加数组时更新引用元素。然而,这两种理论都具有很差的空间/时间性能含义,所以我认为它们不太可能。 编辑:


我误解了数组如何存储元素,我假设它们直接存储元素,但实际上它们存储引用,这意味着元素和列表[500]都指向堆上的某个对象,解决了我不理解的问题

当内部存储
ArrayList
元素的数组变满时,将创建新的、更大的数组,并将以前数组中的所有元素复制到具有相同索引的新数组中,现在有空间容纳新元素。垃圾收集器将去掉以前的数组,不再需要任何数组

您可能需要查看
ArrayList
的实现代码,以了解它如何“在引擎盖下”工作的详细信息

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


请注意,
ArrayList
的工作方式与数组不同(例如,
A
s的数组是
A[]
),它不是一个固定大小的集合-
ArrayList
在添加或删除元素时更改其大小-例如。G如果删除索引0处的元素(
aList.remove(0);
),则存储在索引1000处的元素现在存储在索引999处,
ArrayList
的大小也从1000更改为999。

当内部存储
ArrayList
元素的数组变满时,正在创建更大的数组,并且以前的数组中的所有元素都将以相同的索引复制到新的数组中,现在有了容纳新元素的空间。垃圾收集器将去掉以前的数组,不再需要任何数组

您可能需要查看
ArrayList
的实现代码,以了解它如何“在引擎盖下”工作的详细信息

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


请注意,
ArrayList
的工作方式与数组不同(例如,
A
s的数组是
A[]
),它不是一个固定大小的集合-
ArrayList
在添加或删除元素时更改其大小-例如。G如果删除索引0处的元素(
aList.remove(0);
),则存储在索引1000处的元素现在存储在索引999处,
ArrayList
的大小也从1000更改为999。

如果您想知道ArrayList内部的工作方式,只需查看您可以在线找到的源代码,例如:

在这里,您可以清楚地看到,内部使用了一个
对象[]
,该对象的大小调整为
int newCapacity=(oldCapacity*3)/2+1当认为必要时


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

< p>如果你想知道一个ARARYLIST是如何在内部工作的,那就看看你可以在网上找到的资源,例如:

在这里,您可以清楚地看到,内部使用了一个
对象[]
,该对象的大小调整为
int newCapacity=(oldCapacity*3)/2+1当认为必要时


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

,这不是java,而是给定的JVM的实现细节。您可以在这里阅读一些内容:例如,这里有关于JVM内部的完整书籍。
一个简单的方法是拥有一个对象的地图,因此您首先参考该地图,然后找到实际对象的当前位置。然后,移动实际对象就很简单了,因为它的地址存储在地图的一个副本中。

可以说这很慢,直接存储地址,不需要在地图中查找对象的额外步骤。这样移动对象将需要更多的工作,尽管仍然有可能,但所有指针都必须更新(由于原始指针不会出现在语言级别上,因此临时转换为数字或存储在某个随机数组中以及类似的魔法在这里不会造成伤害,因此您可以始终跟踪某个对象是否是指向正在移动的对象的指针).

这不是Java,而是给定JVM的实现细节。您可以在这里阅读一些内容:例如,有关于JVM内部的完整书籍。
一个简单的方法是拥有一个对象的映射,因此您首先参考该映射,然后找到实际对象的当前位置。然后,移动实际对象很简单,因为它的地址存储在该映射中的单个副本中。
可以说这很慢,直接存储地址,不需要额外的步骤来查找