我如何克隆一个数组列表,也克隆其项目在Java?

例如,我有:

ArrayList<Dog> dogs = getDogs();
ArrayList<Dog> clonedList = ....something to do with dogs....

我希望clonedList中的对象与dogs list中的对象不一样。


当前回答

我想我找到了一个非常简单的方法来创建一个深度复制数组列表。假设你想复制一个字符串数组列表arrayA。

ArrayList<String>arrayB = new ArrayList<String>();
arrayB.addAll(arrayA);

如果对你不起作用请告诉我。

其他回答

您将需要迭代这些项,并逐个克隆它们,将克隆放入结果数组中。

public static List<Dog> cloneList(List<Dog> list) {
    List<Dog> clone = new ArrayList<Dog>(list.size());
    for (Dog item : list) clone.add(item.clone());
    return clone;
}

显然,要做到这一点,必须让Dog类实现Cloneable接口并重写clone()方法。

其他的海报是正确的:你需要迭代列表并复制到一个新的列表。

然而…… 如果列表中的对象是不可变的-你不需要克隆它们。如果你的对象有一个复杂的对象图,它们也需要是不可变的。

不可变性的另一个好处是它们也是线程安全的。

List<Dog> dogs;
List<Dog> copiedDogs = dogs.stream().map(dog -> SerializationUtils.clone(dog)).Collectors.toList());

这将深度复制每个狗

下面是一个使用泛型模板类型的解决方案:

public static <T> List<T> copyList(List<T> source) {
    List<T> dest = new ArrayList<T>();
    for (T item : source) { dest.add(item); }
    return dest;
}

一种糟糕的方法是用反思来做这件事。这种方法对我很管用。

public static <T extends Cloneable> List<T> deepCloneList(List<T> original) {
    if (original == null || original.size() < 1) {
        return new ArrayList<>();
    }

    try {
        int originalSize = original.size();
        Method cloneMethod = original.get(0).getClass().getDeclaredMethod("clone");
        List<T> clonedList = new ArrayList<>();

        // noinspection ForLoopReplaceableByForEach
        for (int i = 0; i < originalSize; i++) {
            // noinspection unchecked
            clonedList.add((T) cloneMethod.invoke(original.get(i)));
        }
        return clonedList;
    } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
        System.err.println("Couldn't clone list due to " + e.getMessage());
        return new ArrayList<>();
    }
}