如何在 Java 中制作 ArrayList<Integer> 的深层副本?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42067086/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 06:21:07  来源:igfitidea点击:

How do I make a deep copy of an ArrayList<Integer> in Java?

javaarraylistdeep-copy

提问by magicLavaLamps

I am basically just trying to make a deep copy of ones and zeroes, so I could have used booleans, but I was wondering how to do this in genereal for integers.

我基本上只是想对 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;
}

回答by px06

The clone()method is protected by the Integerclass, so you cannot call Integer.clone()outside of that class. What you can do instead is create a newInteger.

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;
}

You can test that this works by doing something like:

您可以通过执行以下操作来测试它是否有效:

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");
        }
    }
}


Tests

测试

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

So from my testing it seems that to create a new reference for copying to a new array, you should use new Integer(). Integeris an immutable object but that reference changes when the value of Integerchanges.

所以从我的测试看来,要创建一个新的引用来复制到一个新的数组,你应该使用new Integer(). Integer是一个不可变的对象,但是当值改变时该引用Integer改变。

回答by Azee

Use streams to copy objects. Easy to read, good for JIT. Following code provides a copy of a list with Integer object copies inside.

使用流复制对象。易于阅读,适合 JIT。以下代码提供了一个列表的副本,其中包含 Integer 对象副本。

private ArrayList<Integer> makeDeepCopyInteger(ArrayList<Integer> a){
    return a.stream().map(val -> new Integer(val)).collect(toList());
}

To copy custom objects other than Integer override implement and call clone()

复制除整数覆盖之外的自定义对象并调用 clone()

return a.stream().map(MyObjectClass::clone).collect(toList());

Instead of clone you can use serialization to json. E.g. as used in BeanUtils.getCopy(sourceBean) in following java-utils

您可以使用序列化到 json 而不是克隆。例如,在 BeanUtils.getCopy(sourceBean) 中使用以下java-utils

回答by slim

You coulddo something like:

可以这样做:

public static List<Integer> clone(List<Integer> source) {
   return source.stream()
       .map( intObj -> new Integer(intObj.intValue()))
       .collect(Collectors.toList());
}

Or, more old-fashioned:

或者,更老式的:

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;
}

Both of these could be made shorter by taking advantage of auto-boxing / auto-unboxing. But I've made it explicit to make it absolutely clear what's going on.

通过利用自动装箱/自动拆箱,这两者都可以缩短。但我已经明确说明了正在发生的事情。

However, it's a pointless exercise - in fact it's actively wasteful of memory and detrimental to performance. Integeris immutable, so it's betterfor references to point at the same instance of Integer. Because it's not possible for the Integerto change value, it's impossible to cause any harm by sharing an instance.

然而,这是一个毫无意义的练习——事实上,它积极地浪费了内存并且不利于表现。Integer是不可变的,所以最好让引用指向Integer. 因为不可能Integer改变值,所以共享实例不可能造成任何伤害。

This holds true for immutable objects in general, and is the reason they are a good thing.

这通常适用于不可变对象,这也是它们是好东西的原因。

You are very unlikely, as a beginner, to find a case in which new Integer(...)is a good idea (or even Integer.valueOf(int i), although this one might return a cached instance). If you already have an Integer, use the one you have:

作为初学者,您不太可能找到一个new Integer(...)好主意的案例(甚至Integer.valueOf(int i),尽管这个案例可能会返回缓存的实例)。如果您已经有了Integer,请使用您拥有的:

 Integer oldVar = ... ;
 Integer newVar = oldVar;

Immutability means that will always be OK. It is impossible for an operation on newVarto corrupt oldVarbecause there is no newVar.setValue(newValue).

不变性意味着永远没问题。操作不可能newVar损坏,oldVar因为没有newVar.setValue(newValue).

If you have an intuse it directly and allow Java's auto-boxing to convert it into an Integer:

如果您int直接使用它并允许 Java 的自动装箱将其转换为Integer

 int oldValue = ... ;
 Integer newValue = oldValue ; // Java will automatically put this through
                               // Integer.valueOf(int i)


You mentioned that you really wanted to work with booleans. You should consider using BitSet.

你提到你真的很想使用布尔值。您应该考虑使用BitSet.

回答by StegSchreck

you'll have to iterate over the items of the list and clone them before, adding them to the new list, as mentioned here:

您必须遍历列表中的项目并在之前克隆它们,将它们添加到新列表中,如下所述:

How to clone ArrayList and also clone its contents?

如何克隆 ArrayList 并克隆其内容?