如何在 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
How do I make a deep copy of an ArrayList<Integer> in Java?
提问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 Integer
class, so you cannot call Integer.clone()
outside of that class. What you can do instead is create a new
Integer.
该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()
. Integer
is an immutable object but that reference changes when the value of Integer
changes.
所以从我的测试看来,要创建一个新的引用来复制到一个新的数组,你应该使用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. Integer
is immutable, so it's betterfor references to point at the same instance of Integer
. Because it's not possible for the Integer
to 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 newVar
to corrupt oldVar
because there is no newVar.setValue(newValue)
.
不变性意味着永远没问题。操作不可能newVar
损坏,oldVar
因为没有newVar.setValue(newValue)
.
If you have an int
use 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:
您必须遍历列表中的项目并在之前克隆它们,将它们添加到新列表中,如下所述: