Java ArrayList副本

uemypmqf  于 2022-10-22  发布在  Java
关注(0)|答案(9)|浏览(168)

我有一个大小为10的ArrayListl1。我将l1分配给新的列表引用类型l2l1l2会指向同一个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();

除了创建2个列表对象和从旧到新复制集合之外,是否没有其他方法可以将列表对象的副本分配给新的引用变量?

nzkunb0c

nzkunb0c1#

是的,赋值只会将l1(这是一个引用)的复制到l2。它们都将引用同一个对象。
不过,创建浅层副本非常简单:

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

(仅举一个例子。)

8nuwlpux

8nuwlpux2#

尝试使用Collections.copy(destination, source);

o4hqfura

o4hqfura3#

是的,l1l2将指向同一引用、同一对象。
如果要基于其他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");

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

bpzcxfmw

bpzcxfmw4#

将值从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);

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

2w3kk1z5

2w3kk1z55#

有一个方法addAll(),用于将一个ArrayList复制到另一个。
例如,您有两个数组列表:sourceListtargetList,请使用下面的代码。

targetList.addAll(源列表)

oo7oh9g9

oo7oh9g96#

Java不传递对象,它传递对象的引用(指针)。所以是的,l2和l1是指向同一对象的两个指针。
如果需要两个内容相同的不同列表,则必须进行显式复制。

wqsoz72f

wqsoz72f7#

List.copyOf➙ 不可修改列表

你问:
没有其他方法分配列表的副本吗
Java9引入了List.of方法,用于使用文字来创建未知具体类的不可修改的List

LocalDate today = LocalDate.now( ZoneId.of( "Africa/Tunis" ) ) ;
List< LocalDate > dates = List.of( 
    today.minusDays( 1 ) ,  // Yesterday
    today ,                 // Today
    today.plusDays( 1 )     // Tomorrow
);

除此之外,我们还获得了List.copyOf。此方法也返回未知具体类的不可修改List

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`.

“不可修改”是指列表中元素的数量,以及每个槽中作为元素保存的对象referent,是固定的。不能添加、删除或替换元素。但是每个元素中的对象referent可以是mutable,也可以不是code run live at IdeOne.com

colors.remove( 2 ) ;          // SUCCEEDS. 
masterColors.remove( 2 ) ;    // FAIL - ERROR.

请参阅此code run live at IdeOne.com
日期。toString():[2020-02-02、2020-02-03、2020-03-04]
颜色。toString():[AliceBlue、PapayaWhip、DarkSlateGray]
masterColors。toString():[AliceBlue、PapayaWhip、Chartreuse、DarkSlateGray]
您询问了对象引用。正如其他人所说,如果您创建一个列表并将其分配给两个引用变量(指针),那么您仍然只有一个列表。两者都指向同一个列表。如果使用任一指针修改列表,则两个指针稍后都会看到更改,因为内存中只有一个列表。
所以你需要做一份清单。如果您希望该副本不可修改,请使用本解答中讨论的List.copyOf方法。在这种方法中,您将得到两个单独的列表,每个列表都包含对相同内容对象的引用。例如,在上面使用String对象表示颜色的示例中,颜色对象在内存中的某个地方浮动。这两个列表包含指向相同颜色对象的指针。这是一张图表。


小时
第一个列表colors是可修改的。这意味着可以删除一些元素,如上面的代码所示,其中我们删除了原来的第三个元素Chartreuse(索引2=序号3)。并且可以添加元素。这些元素可以更改为指向其他String,例如OliveDrabCornflowerBlue
相反,masterColors的四个元素是固定的。不去除,不添加,不替换其他颜色。List实现是不可修改的。

o3imoua4

o3imoua48#

只是为了完成:上面所有的答案都是一个浅薄的副本——保留原始对象的引用。如果您想要一个深度拷贝,列表中的(reference-)类必须实现一个clone/copy方法,该方法提供单个对象的深度拷贝。然后您可以使用:

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

kgqe7b3p9#

试试这个ArrayList它很好

ArrayList<Integer> oldList = new ArrayList<>(Integer);
oldList.add(1);
oldList.add(2);

ArrayList<Integer> newList = new ArrayList<>(oldList);
// now newList contains 1, 2

相关问题