我有两个List:
List<Object> listA = new ArrayList<Object>();
List<Object> newListB = new ArrayList<Object>();
如何将listA的内容复制到newListB中,例如,如果我更改了复制列表中的一个元素,我不想在原始列表中更改它。
答案 0 :(得分:1)
您可以使用Java深度克隆的概念:
基本理念是:
您有一个Java对象,并且您希望对其进行完整的克隆(复制)。
通过将类标记为Serializable
,您可以将它们写为对象流,然后将它们作为不同的对象读回。
当您将对象作为不同的对象重新读回时,您很快就会对原始对象进行深度克隆。
Java深度克隆方法
正确回答,以下方法将允许您深入克隆Java对象:
/**
* This method makes a "deep clone" of any Java object it is given.
*/
public static Object deepClone(Object object) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(object);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
}
catch (Exception e) {
e.printStackTrace();
return null;
}
}
在以下链接中找到更多详细信息:
答案 1 :(得分:1)
我不敢告诉你克隆在java中被破坏了:
http://www.javapractices.com/topic/TopicAction.do?Id=71
所以你最好需要实现深层复制方法(这会带来O(log n)问题)
List<Point> listA = new ArrayList<>();
listA.add(new Point(0, 0));
listA.add(new Point(1, 1));
listA.add(new Point(2, 2));
List<Point> newListB = new ArrayList<>();
for (Point point : listA) {
newListB.add(new Point(point));
}
System.out.println("Before deep copy");
System.out.println(listA);
System.out.println(newListB);
listA.get(0).setX(987);
listA.get(0).setY(987);
System.out.println("after changes ");
System.out.println(listA);
System.out.println(newListB);
答案 2 :(得分:1)
您可以使用Reflection将一个列表的所有元素深层复制到另一个列表。请参阅下面的示例代码,该代码可以扩展以满足您的需求,更多(更深层)的案例等。
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class Main {
public static void main(String[] args) {
List<Object> listA = new ArrayList<>();
listA.add(false);
listA.add(123);
listA.add("test");
listA.add(new Foo(1, "foo", 7, new Bar(2)));
System.out.println("==ListA==");
listA.forEach(x -> System.out.println(x));
List<Object> listB = new ArrayList<>(listA.size());
for (Object obj : listA) {
try {
Object o = null;
if (isPrimitiveWrapperClassOrString(obj.getClass())) {
o = newInstance(obj);
} else {
o = obj.getClass().newInstance();
copyValues(obj, o);
}
listB.add(o);
} catch (NoSuchMethodException e) {
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
System.out.println("\n==ListB==");
listB.forEach(x -> System.out.println(x));
// Modify listB
listB.set(0, true);
listB.set(1, 456);
((Foo)listB.get(3)).setId(2);
((Bar)((Foo)listB.get(3)).getBar()).setId(9);
System.out.println("\n==ListA after modifying listB==");
listA.forEach(x -> System.out.println(x));
System.out.println("\n==ListB==");
listB.forEach(x -> System.out.println(x));
}
private static Object newInstance(Object obj) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class classType = obj.getClass();
Object o = null;
if (classType == Boolean.class) {
Method method = classType.getDeclaredMethod("booleanValue", null);
boolean value = (boolean) method.invoke(obj, null);
o = classType.getConstructor(boolean.class).newInstance(value);
} else if (classType == Byte.class) {
Method method = classType.getDeclaredMethod("byteValue", null);
byte value = (byte) method.invoke(obj, null);
o = classType.getConstructor(byte.class).newInstance(value);
} else if (classType == Short.class) {
Method method = classType.getDeclaredMethod("shortValue", null);
short value = (short) method.invoke(obj, null);
o = classType.getConstructor(short.class).newInstance(value);
} else if (classType == Integer.class) {
Method method = classType.getDeclaredMethod("intValue", null);
int value = (int) method.invoke(obj, null);
o = classType.getConstructor(int.class).newInstance(value);
} else if (classType == Long.class) {
Method method = classType.getDeclaredMethod("longValue", null);
long value = (long) method.invoke(obj, null);
o = classType.getConstructor(long.class).newInstance(value);
} else if (classType == Float.class) {
Method method = classType.getDeclaredMethod("floatValue", null);
float value = (float) method.invoke(obj, null);
o = classType.getConstructor(float.class).newInstance(value);
} else if (classType == Double.class) {
Method method = classType.getDeclaredMethod("doubleValue", null);
double value = (double) method.invoke(obj, null);
o = classType.getConstructor(double.class).newInstance(value);
} else if (classType == Character.class) {
Method method = classType.getDeclaredMethod("charValue", null);
char value = (char) method.invoke(obj, null);
o = classType.getConstructor(char.class).newInstance(value);
} else if (classType == String.class) {
Method method = classType.getDeclaredMethod("toString", null);
String value = (String) method.invoke(obj, null);
o = classType.getConstructor(String.class).newInstance(value);
}
return o;
}
private static void copyValues(Object objF, Object objT) throws IllegalAccessException, InstantiationException {
Class classType = objF.getClass();
for (Field field : classType.getDeclaredFields()) {
field.setAccessible(true);
Class fieldType = field.getType();
if (isPrimitiveWrapperClassOrString(fieldType)) {
field.set(objT, field.get(objF));
} else {
Object objN = field.get(objT);
if (Objects.isNull(objN)) objN = field.getType().newInstance();
copyValues(field.get(objF), objN);
field.set(objT, objN);
}
}
}
private static boolean isPrimitiveWrapperClassOrString(Class classType) {
return classType == Boolean.class || classType == boolean.class ||
classType == Byte.class || classType == byte.class ||
classType == Short.class || classType == short.class ||
classType == Integer.class || classType == int.class ||
classType == Long.class || classType == long.class ||
classType == Float.class || classType == float.class ||
classType == Double.class || classType == double.class ||
classType == Character.class || classType == char.class ||
classType == String.class;
}
}
class Foo {
private int id;
private String label;
private Integer stock;
private Bar bar;
public Foo() { }
public Foo(int id, String label, Integer stock, Bar bar) {
this.id = id;
this.label = label;
this.stock = stock;
this.bar = bar;
}
public int getId() { return this.id; }
public void setId(int id) { this.id = id; }
public String getLabel() { return this.label; }
public void setLabel() { this.label = label; }
public Integer getStock() { return this.stock; }
public void setStock(Integer stock) { this.stock = stock; }
public Bar getBar() { return this.bar; }
public void setBar(Bar bar) { this.bar = bar; }
@Override
public String toString() {
return String.format("%s | %d | %d | %s", this.label, this.id, this.stock, this.bar);
}
}
class Bar {
private int id;
public Bar() {}
public Bar(int id) { this.id = id; }
public int getId() { return this.id; }
public void setId(int id) { this.id = id; }
@Override
public String toString() { return "Bar: " + this.id; }
}
哪个输出
==ListA==
false
123
test
foo | 1 | 7 | Bar: 2
==ListB==
false
123
test
foo | 1 | 7 | Bar: 2
==ListA after modifying listB==
false
123
test
foo | 1 | 7 | Bar: 2
==ListB==
true
456
test
foo | 2 | 7 | Bar: 9
答案 3 :(得分:0)
尝试这样的事情。
List<Object> listA = new ArrayList<Object>();
List<Object > newListB = new ArrayList<Object>();
for (Object object : listA ) {
newListB .add(object .clone());
}
相同的工作示例如下
public static void main(String[] args){
TestClass test = new TestClass(1);
List<TestClass> listA = new ArrayList<TestClass>();
listA.add(test);
List<TestClass> newListB = new ArrayList<TestClass>();
for (TestClass test1: listA ) {
TestClass classSome = new TestClass();
classSome = (TestClass)test1.clone();
newListB.add(classSome );
}
System.out.println("listA id ="+listA.get(0).id);
System.out.println("newListB id ="+newListB .get(0).id);
newListB .get(0).setId(15);
System.out.println("listA id ="+listA.get(0).id);
System.out.println("newListB id ="+newListB .get(0).id);
}
TestClass将如下所示
class TestClass implements Cloneable{
int id;
public TestClass(){
}
public TestClass(int id){
this.id = id;
}
public int getId(){
return this.id;
}
public void setId(int id){
this.id=id;
}
@Override
public Object clone() {
try {
return (TestClass)super.clone();
}
catch (CloneNotSupportedException e) {
return null;
// This should never happen
}
}
}