如何在 Java 中制作 ArrayList<Integer> 的深层副本? [复制]
Posted
技术标签:
【中文标题】如何在 Java 中制作 ArrayList<Integer> 的深层副本? [复制]【英文标题】:How do I make a deep copy of an ArrayList<Integer> in Java? [duplicate] 【发布时间】:2017-06-23 08:29:06 【问题描述】:我基本上只是想对 1 和 0 进行深度复制,所以我可以使用布尔值,但我想知道如何在一般情况下为整数执行此操作。
private ArrayList<Integer> makeDeepCopyInteger(ArrayList<Integer> a)
ArrayList<Integer> newA = new ArrayList<>(a.size());
for (int i = 0; i < a.size(); i++)
int newInt = 0;
if (a.get(i) == 1)
newInt = 1;
newA.add(newInt);
return newA;
【问题讨论】:
既然整数是不可变的,为什么要深拷贝它们? 【参考方案1】:clone()
方法受Integer
类的保护,因此您不能在该类之外调用Integer.clone()
。您可以做的是创建一个 new
整数。
private ArrayList<Integer> makeDeepCopyInteger(ArrayList<Integer> old)
ArrayList<Integer> copy = new ArrayList<Integer>(old.size());
for(Integer i : old)
copy.add(new Integer(i));
return copy;
您可以通过执行以下操作来测试它是否有效:
public static void main (String[] args) throws java.lang.Exception
ArrayList<Integer> arr = new ArrayList<>();
for(int i = 0; i<5; i++)
arr.add(new Integer(i));
ArrayList<Integer> x = makeDeepCopyInteger(arr);
for(int i = 0; i<x.size(); i++)
if(arr.get(i) == x.get(i))
System.out.println("Same object");
else
System.out.println("Not the same object");
测试
Integer a = new Integer(1);
Integer b = new Integer(a);
System.out.println(a==b); // true
System.out.println(System.identityHashCode(a) == (System.identityHashCode(b))); // false;
Integer a = new Integer(1);
Integer b = a;
System.out.println(a==b); // true
System.out.println(System.identityHashCode(a) == (System.identityHashCode(b))); // true
所以从我的测试看来,要创建一个用于复制到新数组的新引用,您应该使用new Integer()
。 Integer
是一个不可变对象,但当 Integer
的值发生变化时,该引用也会发生变化。
【讨论】:
由于Integer
是不可变的,您不需要创建它的副本。
@Kayaman 我对此进行了一些测试,请参阅我的编辑。也许我很困惑,但由于不创建副本,它似乎保留了旧的参考。
这没有什么问题。由于Integer
的值不能改变,例如,如果您有1000 个列表都引用相同的17
并不重要。你的最后一段是错误的。由于Integer
是不可变的,所以它的值不能改变。【参考方案2】:
使用流来复制对象。易于阅读,适合 JIT。以下代码提供了一个列表副本,其中包含 Integer 对象副本。
private ArrayList<Integer> makeDeepCopyInteger(ArrayList<Integer> a)
return a.stream().map(val -> new Integer(val)).collect(toList());
复制除整数以外的自定义对象覆盖实现并调用clone()
return a.stream().map(MyObjectClass::clone).collect(toList());
您可以使用序列化到 json 来代替克隆。例如。在 BeanUtils.getCopy(sourceBean) 中使用 java-utils
【讨论】:
欢迎来到堆栈溢出 :-) 请看How to Answer。您应该提供一些信息为什么您的代码可以解决问题。仅代码答案对社区没有用处。【参考方案3】:您可以执行以下操作:
public static List<Integer> clone(List<Integer> source)
return source.stream()
.map( intObj -> new Integer(intObj.intValue()))
.collect(Collectors.toList());
或者,更老式的:
public static List<Integer> clone(List<Integer> source)
List<Integer> newList = new ArrayList<>();
for(Integer intObj : source)
newList.add(new Integer(intObj.intValue()));
return newList;
通过利用自动装箱/自动拆箱,可以缩短这两者。但我已经明确表示要绝对清楚发生了什么。
但是,这是一种毫无意义的练习 - 事实上,它会浪费内存并且不利于性能。 Integer
是不可变的,因此更好的引用指向Integer
的同一实例。因为Integer
不可能改变值,所以不可能通过共享实例造成任何伤害。
这适用于一般的不可变对象,这也是它们是好东西的原因。
作为初学者,您不太可能找到new Integer(...)
是一个好主意的情况(甚至Integer.valueOf(int i)
,尽管这可能会返回一个缓存实例)。如果您已经有Integer
,请使用您拥有的:
Integer oldVar = ... ;
Integer newVar = oldVar;
不变性意味着永远没问题。对newVar
的操作不可能破坏oldVar
,因为没有newVar.setValue(newValue)
。
如果您有int
,请直接使用它并允许Java 的自动装箱将其转换为Integer
:
int oldValue = ... ;
Integer newValue = oldValue ; // Java will automatically put this through
// Integer.valueOf(int i)
您提到您真的很想使用布尔值。您应该考虑使用BitSet
。
【讨论】:
【参考方案4】:您必须遍历列表中的项目并在之前克隆它们,然后将它们添加到新列表中,如下所述:
How to clone ArrayList and also clone its contents?
【讨论】:
以上是关于如何在 Java 中制作 ArrayList<Integer> 的深层副本? [复制]的主要内容,如果未能解决你的问题,请参考以下文章