Java ArrayList副本

Java ArrayList副本,java,arraylist,Java,Arraylist,我有一个大小为10的ArrayListl1。我将l1分配给新的列表引用类型l2。l1和l2是否指向相同的ArrayList对象?或者是ArrayList对象的副本分配给了l2 使用l2引用时,如果我更新列表对象,它也会反映l1引用类型中的更改 例如: List<Integer> l1 = new ArrayList<Integer>(); for (int i = 1; i <= 10; i++) { l1.add(i); } List l2 = l1;

我有一个大小为10的
ArrayList
l1
。我将
l1
分配给新的列表引用类型
l2
l1
l2
是否指向相同的
ArrayList
对象?或者是
ArrayList
对象的副本分配给了
l2

使用
l2
引用时,如果我更新列表对象,它也会反映
l1
引用类型中的更改

例如:

List<Integer> l1 = new ArrayList<Integer>();
for (int i = 1; i <= 10; i++) {
    l1.add(i);
}

List l2 = l1;
l2.clear();
List l1=new ArrayList();

对于(int i=1;iYes),赋值将把
l1
(这是一个引用)的值复制到
l2
。它们都将引用同一个对象

不过,创建浅层副本非常简单:

List<Integer> newList = new ArrayList<>(oldList);
List newList=newarraylist(oldList);

(就像一个例子。)

试着使用Java不传递对象,它传递引用(指针)到对象。因此,是的,l2和l1是指向同一对象的两个指针


如果需要两个具有相同内容的不同列表,则必须进行显式复制。

l1
l2
将指向相同的引用、相同的对象

如果要基于另一个ArrayList创建新的ArrayList,请执行以下操作:

List<String> l1 = new ArrayList<String>();
l1.add("Hello");
l1.add("World");
List<String> l2 = new ArrayList<String>(l1); //A new arrayList.
l2.add("Everybody");
List l1=new ArrayList();
l1.加上(“你好”);
l1.添加(“世界”);
列表l2=新的ArrayList(l1);//一个新的ArrayList。
l2.添加(“所有人”);

结果将是,
l1
仍将有2个元素,
l2
将有3个元素。

将值从src ArrayList复制到dest ArrayList的另一种方便方法如下:

ArrayList<String> src = new ArrayList<String>();
src.add("test string1");
src.add("test string2");
ArrayList<String> dest= new ArrayList<String>();
dest.addAll(src);
ArrayList src=new ArrayList();
src.添加(“测试字符串1”);
src.添加(“测试字符串2”);
ArrayList dest=新的ArrayList();
目的地地址(src);

这是值的实际复制,而不仅仅是引用的复制。

有一种方法addAll(),用于将一个ArrayList复制到另一个ArrayList

例如,您有两个数组列表:sourceList和targetList,请使用下面的代码

targetList.addAll(sourceList);
List.copyOf
➙ 不可修改列表 你问:

没有其他方法分配列表副本吗

Java9带来了使用文本创建未知的不可修改的具体类的方法

LocalDate today = LocalDate.now( ZoneId.of( "Africa/Tunis" ) ) ;
List< LocalDate > dates = List.of( 
    today.minusDays( 1 ) ,  // Yesterday
    today ,                 // Today
    today.plusDays( 1 )     // Tomorrow
);
List< String > colors = new ArrayList<>( 4 ) ;          // Creates a modifiable `List`. 
colors.add ( "AliceBlue" ) ;
colors.add ( "PapayaWhip" ) ;
colors.add ( "Chartreuse" ) ;
colors.add ( "DarkSlateGray" ) ;
List< String > masterColors = List.copyOf( colors ) ;   // Creates an unmodifiable `List`.
“不可修改”是指列表中元素的数量,每个插槽中作为元素保存的对象引用是固定的。您不能添加、删除或替换元素。但每个元素中保存的对象引用可能是固定的,也可能不是固定的

看这个

dates.toString():[2020-02-022020-02-032020-02-04]

colors.toString():[AliceBlue、PapayaWhip、深灰色]

MasterColor.toString():[AliceBlue、PapayaWhip、黄绿色、深灰色]

您询问了对象引用。正如其他人所说,如果您创建一个列表并将其分配给两个引用变量(指针),您仍然只有一个列表。两个列表都指向同一个列表。如果您使用任一指针修改列表,两个指针稍后都会看到更改,因为内存中只有一个列表

因此,您需要制作列表的副本。如果您希望该副本不可修改,请使用本答案中讨论的
list.copyOf
方法。在这种方法中,您将得到两个单独的列表,每个列表中的元素都包含对相同内容对象的引用。例如,在上面的示例中,使用
String
对象表示颜色,颜色对象在内存中的某个位置浮动。这两个列表包含指向相同颜色对象的指针。这是一个图表

第一个列表
colors
是可修改的。这意味着可以删除一些元素,如上面代码所示,我们删除了原始的第三个元素
Chartreuse
(索引2=序号3)。可以添加元素。并且可以将元素更改为指向其他一些
字符串
,例如
OliveDrab
CornflowerBlue

相反,
masterColors
的四个元素是固定的。不删除、不添加和不替换其他颜色。
List
的实现是不可修改的。

只是为了完成: 上面所有的答案都是为了一个浅拷贝——保留原始对象的引用 克隆/复制方法,该方法提供单个对象的深度副本。然后,您可以使用:

newList.addAll(oldList.stream().map(s->s.clone()).collect(Collectors.toList()));

是否可以只将arraylist的一部分高效地复制到新的arraylist。例如:将位置5到10之间的元素从一个arraylist复制到另一个新的arraylist。在我的应用程序中,范围会大得多。@Ashwin:这是一个O(N)操作,但是是的……您可以使用
List.subList
来获取“视图”在原始列表的一部分上。如果数组列表嵌套在
(ArrayList)中该怎么办
?这会递归地创建所有子ArrayList对象的副本吗?@Cat:不会……这只是一个浅层副本。@ShanikaEdiriweera:你可以用streams流畅地完成它,是的。但棘手的部分是创建一个深层副本,而大多数对象都不会提供。如果你考虑到具体情况,我建议你向deta提出一个新问题ils.你如何制作“显式副本”?我想你说的是深度副本?我不完全确定这是否准确。我的测试表明相反(仍然引用同一对象)。当使用ArrayList和ArrayAdapter时,此解决方案对我有效。此答案是错误的。addAll()正如invertigo所说,只是复制引用。这不是深度复制。对于ArrayList来说,这个答案是可以接受的,因为字符串是不可变的,但用OP的例子ArraList试试,你会发现它只是复制引用。我想这不是我的日子。事实证明Integer和Long等类也是不可变的,所以Harshal的答案是wArrayList和ArrayList等简单情况下的orks。失败的地方是对于不可变的复杂对象
newList.addAll(oldList.stream().map(s->s.clone()).collect(Collectors.toList()));