Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何克隆ArrayList并同时克隆其内容?_Java_Collections_Clone_Deep Copy - Fatal编程技术网

Java 如何克隆ArrayList并同时克隆其内容?

Java 如何克隆ArrayList并同时克隆其内容?,java,collections,clone,deep-copy,Java,Collections,Clone,Deep Copy,如何克隆ArrayList并在Java中克隆其项 例如,我有: ArrayList<Dog> dogs = getDogs(); ArrayList<Dog> clonedList = ....something to do with dogs.... arraylistdogs=getDogs(); ArrayList克隆列表=…与狗有关。。。。 我希望clonedList中的对象与dogs list中的对象不同。您需要迭代这些项,然后逐个克隆它们,并将克隆结果放入

如何克隆
ArrayList
并在Java中克隆其项

例如,我有:

ArrayList<Dog> dogs = getDogs();
ArrayList<Dog> clonedList = ....something to do with dogs....
arraylistdogs=getDogs();
ArrayList克隆列表=…与狗有关。。。。

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

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

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;
}
公共静态列表克隆列表(列表列表){
List clone=newarraylist(List.size());
对于(狗项:列表)clone.add(item.clone());
返回克隆;
}

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

您需要手动克隆
ArrayList
(通过迭代它并将每个元素复制到新的
ArrayList
),因为
clone()
不会为您这样做。原因是
ArrayList
中包含的对象本身可能无法实现
Clonable


编辑:。。。这正是Varkhan的代码所做的。

我个人会为Dog添加一个构造函数:

class Dog
{
    public Dog()
    { ... } // Regular constructor

    public Dog(Dog dog) {
        // Copy all the fields of Dog.
    }
}
然后迭代(如Varkhan的回答所示):

公共静态列表克隆列表(列表狗列表){
List clonedList=newarraylist(dogList.size());
用于(狗:狗名单){
克隆列表。添加(新狗(狗));
}
返回克隆列表;
}
我发现这样做的好处是,您不需要在Java中处理坏的可克隆内容。它还与复制Java集合的方式相匹配


另一个选择是编写自己的IClonable接口并使用它。这样你就可以编写一个通用的克隆方法。

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

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


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

我认为当前的绿色答案是不好的,为什么你会问

  • 它可能需要添加大量代码
  • 它要求您列出所有要复制的列表并执行此操作
序列化的方式在我看来也是不好的,你可能不得不到处添加Serializable

那么解决方案是什么:

List<Dog> clonedDogs = dogs.stream().map(Dog::new).collect(toList());
List<Dog> clonedDogs = dogs.stream().map(d -> d.clone()).collect(toList());
public class Dog implements Serializable {
    private String name;
    private int age;

    public Dog() {
        // Class with only mutable fields!
        this.name = "NO_NAME";
        this.age = -1;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
List dogs: [Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]
Now list dogs are deep copied into list clonedDogs.
List dogs after change: [Dog{name='Bella', age=3}, Dog{name='Molly', age=4}]
After change in list dogs, no impact/change in list clonedDogs:
[Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]
public class Dog {
    private String name;
    private int age;

    public Dog() {
        // Class with only mutable fields!
        this.name = "NO_NAME";
        this.age = -1;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    /**
     * Returns a deep copy of the Dog
     * @return new instance of {@link Dog}
     */
    public Dog clone() {
        Dog newDog = new Dog();
        newDog.setName(this.name);
        newDog.setAge(this.age);
        return newDog;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
List dogs: [Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]
Now list dogs are deep copied into list clonedDogs.
List dogs after change: [Dog{name='Bella', age=3}, Dog{name='Molly', age=4}]
After change in list dogs, no impact/change in list clonedDogs:
[Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]
Java深度克隆库 克隆库是一个小型的开源(apache许可证)java库,用于深度克隆对象。对象不必实现可克隆接口。这个库可以有效地克隆任何java对象。如果您不希望修改缓存对象,或者希望创建对象的深度副本,则可以在缓存实现中使用它

Cloner cloner=new Cloner();
XX clone = cloner.deepClone(someObjectOfTypeXX);

请访问

这里有一个使用通用模板类型的解决方案:

public static <T> List<T> copyList(List<T> source) {
    List<T> dest = new ArrayList<T>();
    for (T item : source) { dest.add(item); }
    return dest;
}
公共静态列表copyList(列表源){
List dest=new ArrayList();
对于(T项:源){dest.add(项);}
返回目的地;
}

所有标准集合都有副本构造函数。使用它们

List<Double> original = // some list
List<Double> copy = new ArrayList<Double>(original); //This does a shallow copy
List original=//一些列表
列表副本=新阵列列表(原件)//这是一个浅显的副本
clone()
的设计有几个错误(请参阅),因此最好避免它

从,第11项:明智地覆盖克隆

考虑到与Cloneable相关的所有问题,可以肯定地说 其他接口不应该扩展它,而类 为继承而设计(第17项)不应实现它。因为 它有很多缺点,一些专家程序员干脆选择不做 重写clone方法,并且永远不要调用它,除非 复制数组。如果为继承设计类,请注意 如果选择不提供性能良好的受保护克隆方法,则 子类不可能实现Cloneable

本书还描述了复制构造函数相对于可克隆/克隆的许多优势

  • 他们不依赖于有风险的语言外物体创造 机制
  • 他们不要求不可强制执行地遵守记录很少的约定
  • 它们与final字段的正确使用没有冲突
  • 它们不会抛出不必要的已检查异常
  • 他们不需要石膏

考虑使用复制构造函数的另一个好处:假设您有一个
HashSet s
,并且希望将其复制为
TreeSet
。clone方法无法提供此功能,但使用转换构造函数很容易:
newtreeset

for your objects override clone()方法


并为Vector obj或ArraiList obj调用.clone()。

使用commons-lang-2.3.jar将java库克隆到列表中的简单方法

链接

如何使用

oldList.........
List<YourObject> newList = new ArrayList<YourObject>();
foreach(YourObject obj : oldList){
   newList.add((YourObject)SerializationUtils.clone(obj));
}
oldList。。。。。。。。。
List newList=newarraylist();
foreach(您的对象对象:旧列表){
add((YourObject)SerializationUtils.clone(obj));
}
我希望这个能有所帮助


:D

导入org.apache.commons.lang.SerializationUtils

有一个方法
SerializationUtils.clone(Object)

范例

this.myObjectCloned = SerializationUtils.clone(this.object);

基本上有三种方法不需要手动迭代,

1使用构造函数

ArrayList<Dog> dogs = getDogs();
ArrayList<Dog> clonedList = new ArrayList<Dog>(dogs);

注意:如果在操作进行过程中修改了指定的集合,则这些操作的行为将是未定义的。

一种令人讨厌的方法是使用反射。像这样的事情对我很有用

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<>();
    }
}
公共静态列表深度克隆列表(列表原件){
if(original==null | | original.size()<1){
返回新的ArrayList();
}
试一试{
int originalSize=original.size();
方法cloneMethod=original.get(0.getClass().getDeclaredMethod(“clon
ArrayList<Dog> clonedDogs = dogs.stream().map(Dog::new).collect(toCollection(ArrayList::new));
dogs.replaceAll(Dog::new);
ArrayList<Dog> clonedDogs = dogs.stream().map(d -> d.clone()).collect(toArrayList());

public static <T> Collector<T, ?, ArrayList<T>> toArrayList() {
    return Collectors.toCollection(ArrayList::new);
}
    // Note: Method is public and returns Dog, not Object
    @Override
    public Dog clone() /* Note: No throws clause here */ { ...
List<Dog> clonedDogs = dogs.stream().map(Dog::clone).collect(toList());
List<CategoryModel> originalList = new ArrayList<>(); // add some items later
String listAsJson = gson.toJson(originalList);
List<CategoryModel> newList = new Gson().fromJson(listAsJson, new TypeToken<List<CategoryModel>>() {}.getType());
ArrayList<String>arrayB = new ArrayList<String>();
arrayB.addAll(arrayA);
ArrayList<Dog> clonedList = new ArrayList<Dog>(name_of_arraylist_that_you_need_to_Clone);
public Class Dog{

private String a,b;

public Dog(){} //no args constructor

public Dog(Dog d){ // copy constructor
   this.a=d.a;
   this.b=d.b;
}

}

 -------------------------

 private List<Dog> createCopy(List<Dog> dogs) {
 List<Dog> newDogsList= new ArrayList<>();
 if (CollectionUtils.isNotEmpty(dogs)) {
 dogs.stream().forEach(dog-> newDogsList.add((Dog) SerializationUtils.clone(dog)));
 }
 return newDogsList;
 }
List<Dog> dogs;
List<Dog> copiedDogs = dogs.stream().map(dog -> SerializationUtils.clone(dog)).Collectors.toList());
ArrayList<Dog> dogs = getDogs();
ArrayList<Dog> clonedList = new ArrayList<Dog>(dogs);
SerializationUtils.clone()
List<Dog> dogs = getDogs(); // We assume it returns a list of Dogs
List<Dog> clonedDogs = new ArrayList<>(dogs);
public class Dog implements Serializable {
    private String name;
    private int age;

    public Dog() {
        // Class with only mutable fields!
        this.name = "NO_NAME";
        this.age = -1;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public static void main(String[] args) {
    Dog dog1 = new Dog();
    dog1.setName("Buddy");
    dog1.setAge(1);

    Dog dog2 = new Dog();
    dog2.setName("Milo");
    dog2.setAge(2);

    List<Dog> dogs = new ArrayList<>(Arrays.asList(dog1,dog2));

    // Output: 'List dogs: [Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]'
    System.out.println("List dogs: " + dogs);

    // Let's clone and make a deep copy of the dogs' ArrayList with external package commons-lang3:
    List<Dog> clonedDogs = dogs.stream().map(dog -> SerializationUtils.clone(dog)).collect(Collectors.toList());
    // Output: 'Now list dogs are deep copied into list clonedDogs.'
    System.out.println("Now list dogs are deep copied into list clonedDogs.");

    // A change on dog1 or dog2 can not impact a deep copy.
    // Let's make a change on dog1 and dog2, and test this
    // statement.
    dog1.setName("Bella");
    dog1.setAge(3);
    dog2.setName("Molly");
    dog2.setAge(4);

    // The change is made on list dogs!
    // Output: 'List dogs after change: [Dog{name='Bella', age=3}, Dog{name='Molly', age=4}]'
    System.out.println("List dogs after change: " + dogs);

    // There is no impact on list clonedDogs's inner objects after the deep copy.
    // The deep copy of list clonedDogs was successful!
    // If clonedDogs would be a shallow copy we would see the change on the field
    // "private String name", the change made in list dogs, when setting the names
    // Bella and Molly.
    // Output clonedDogs:
    // 'After change in list dogs, no impact/change in list clonedDogs:\n'
    // '[Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]\n'
    System.out.println("After change in list dogs, no impact/change in list clonedDogs: \n" + clonedDogs);
}
List dogs: [Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]
Now list dogs are deep copied into list clonedDogs.
List dogs after change: [Dog{name='Bella', age=3}, Dog{name='Molly', age=4}]
After change in list dogs, no impact/change in list clonedDogs:
[Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]
clone()
public class Dog {
    private String name;
    private int age;

    public Dog() {
        // Class with only mutable fields!
        this.name = "NO_NAME";
        this.age = -1;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    /**
     * Returns a deep copy of the Dog
     * @return new instance of {@link Dog}
     */
    public Dog clone() {
        Dog newDog = new Dog();
        newDog.setName(this.name);
        newDog.setAge(this.age);
        return newDog;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public static void main(String[] args) {
    Dog dog1 = new Dog();
    dog1.setName("Buddy");
    dog1.setAge(1);

    Dog dog2 = new Dog();
    dog2.setName("Milo");
    dog2.setAge(2);

    List<Dog> dogs = new ArrayList<>(Arrays.asList(dog1,dog2));

    // Output: 'List dogs: [Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]'
    System.out.println("List dogs: " + dogs);

    // Let's clone and make a deep copy of the dogs' ArrayList:
    List<Dog> clonedDogs = dogs.stream().map(dog -> dog.clone()).collect(Collectors.toList());
    // Output: 'Now list dogs are deep copied into list clonedDogs.'
    System.out.println("Now list dogs are deep copied into list clonedDogs.");

    // A change on dog1 or dog2 can not impact a deep copy.
    // Let's make a change on dog1 and dog2, and test this
    // statement.
    dog1.setName("Bella");
    dog1.setAge(3);
    dog2.setName("Molly");
    dog2.setAge(4);

    // The change is made on list dogs!
    // Output: 'List dogs after change: [Dog{name='Bella', age=3}, Dog{name='Molly', age=4}]'
    System.out.println("List dogs after change: " + dogs);

    // There is no impact on list clonedDogs's inner objects after the deep copy.
    // The deep copy of list clonedDogs was successful!
    // If clonedDogs would be a shallow copy we would see the change on the field
    // "private String name", the change made in list dogs, when setting the names
    // Bella and Molly.
    // Output clonedDogs:
    // 'After change in list dogs, no impact/change in list clonedDogs:\n'
    // '[Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]\n'
    System.out.println("After change in list dogs, no impact/change in list clonedDogs: \n" + clonedDogs);
}
List dogs: [Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]
Now list dogs are deep copied into list clonedDogs.
List dogs after change: [Dog{name='Bella', age=3}, Dog{name='Molly', age=4}]
After change in list dogs, no impact/change in list clonedDogs:
[Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.9</version>
</dependency>