Java ArrayList副本
我有一个大小为10的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;
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()));