Java 将一个列表的内容复制到另一个列表(非引用)

Java 将一个列表的内容复制到另一个列表(非引用),java,list,collections,Java,List,Collections,我有两份清单: List<Object> listA = new ArrayList<Object>(); List<Object> newListB = new ArrayList<Object>(); List listA=new ArrayList(); List newListB=newarraylist(); 如何将listA的内容复制到newListB中,例如,如果我更改了复制列表中的一个元素,我不想在原始列表中更改它。您可以使用J

我有两份清单:

List<Object> listA = new ArrayList<Object>();
List<Object> newListB = new ArrayList<Object>();
List listA=new ArrayList();
List newListB=newarraylist();

如何将listA的内容复制到newListB中,例如,如果我更改了复制列表中的一个元素,我不想在原始列表中更改它。

您可以使用Java深度克隆的概念:

其基本思想是:

您有一个Java对象,并且希望对其进行完整的克隆(拷贝)。 通过将类标记为可序列化,可以将它们作为对象流写出,然后作为不同的对象读回。 当您将对象作为另一个对象读回时,您很快就会得到原始对象的深层克隆

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;
   }
 }
请在以下链接中查找更多详细信息:


试试这样的方法

 List<Object> listA = new ArrayList<Object>();
    List<Object > newListB = new ArrayList<Object>();

    for (Object object : listA ) {
      newListB .add(object .clone());
    }

我不敢告诉您克隆在java中已损坏:

  • 因此,您最好实现深度复制方法(这将给您带来一个O(logn)问题)

    List listA=new ArrayList();
    添加(新点(0,0));
    增加(新的第(1,1)点);
    增加(新的第(2,2)点);
    List newListB=newarraylist();
    对于(点:listA){
    新增(新点(点));
    }
    System.out.println(“深度复制前”);
    System.out.println(listA);
    System.out.println(newListB);
    listA.get(0.setX(987);
    listA.get(0.setY(987);
    System.out.println(“变更后”);
    System.out.println(listA);
    System.out.println(newListB);
    
只需使用构造函数publicArrayList(集合c)通过传递第一个列表来构造第二个列表。它使用第一个列表中的所有项,按照迭代器给定的顺序初始化列表。 可以使用反射将一个列表中的所有元素深度复制到另一个列表中。请参阅下面的示例代码,该代码可以扩展以满足您的需求、更多(更深入)的情况等

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

这不是我想要的,因为如果我更改复制列表中的一个元素,它也会更改原始列表中的元素。@Jens这不是该列表的副本。请移开旗帜。他并不是在问要克隆的名单。但他想克隆列表中的对象。@Dhiraj是的,它没有重复。谢谢您的帮助attention@Xenu我会尽力帮助你继续使用评论。如果他撤掉国旗,我会给你详细的答复。到目前为止,只需迭代listA并克隆每个元素并添加到NewListBy您只需将
listA
传递到
deepClone()
,然后将返回的对象分配给
newListB
(转换后)。序列化成本很高只要对象是可克隆的,这个想法就行了,但在克隆之前,您需要将每个对象强制转换为可克隆的。@OleV.V。不,你没有。你不需要投任何东西。您需要实现
Cloneable
,并遵循其相当复杂的规则。最好编写一个复制构造函数。methode clone()在JavaAPI中被破坏了。您可以创建自己的方法来实现这一点。但如果你用其他方法来实现这一点。请在回答这个问题时提供这些信息。@OleV.V。第一个片段就是一个例子。但我已经给出了另外两个片段,这是这个的实际实现。我的答案是更具体的列表是有固定类型的对象。对于具有不同类型的对象列表,我还没有考虑它。我也很好奇如何将此应用于通用列表。这复制了参考资料,与询问者的要求相反。我编辑了我的答案,因为我后来知道您需要深度复制
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
                 }
            }
    }
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);
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