How to clone ArrayList and also clone its contents?

后端 未结 21 1917
小鲜肉
小鲜肉 2020-11-21 06:42

How can I clone an ArrayList and also clone its items in Java?

For example I have:

ArrayList dogs = getDogs();
ArrayList

        
相关标签:
21条回答
  • 2020-11-21 07:15

    You will need to iterate on the items, and clone them one by one, putting the clones in your result array as you go.

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

    For that to work, obviously, you will have to get your Dog class to implement the Cloneable interface and override the clone() method.

    0 讨论(0)
  • 2020-11-21 07:16

    I have used this option always:

    ArrayList<Dog> clonedList = new ArrayList<Dog>(name_of_arraylist_that_you_need_to_Clone);
    
    0 讨论(0)
  • 2020-11-21 07:16
    List<Dog> dogs;
    List<Dog> copiedDogs = dogs.stream().map(dog -> SerializationUtils.clone(dog)).Collectors.toList());
    

    This will deep copy each dog

    0 讨论(0)
  • 2020-11-21 07:17

    Basically there are three ways without iterating manually,

    1 Using constructor

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

    2 Using addAll(Collection<? extends E> c)

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

    3 Using addAll(int index, Collection<? extends E> c) method with int parameter

    ArrayList<Dog> dogs = getDogs();
    ArrayList<Dog> clonedList = new ArrayList<Dog>();
    clonedList.addAll(0, dogs);
    

    NB : The behavior of these operations will be undefined if the specified collection is modified while the operation is in progress.

    0 讨论(0)
  • 2020-11-21 07:22

    for you objects override clone() method

    class You_class {
    
        int a;
    
        @Override
        public You_class clone() {
            You_class you_class = new You_class();
            you_class.a = this.a;
            return you_class;
        }
    }
    

    and call .clone() for Vector obj or ArraiList obj....

    0 讨论(0)
  • 2020-11-21 07:24

    Java 8 provides a new way to call the copy constructor or clone method on the element dogs elegantly and compactly: Streams, lambdas and collectors.

    Copy constructor:

    List<Dog> clonedDogs = dogs.stream().map(Dog::new).collect(toList());
    

    The expression Dog::new is called a method reference. It creates a function object which calls a constructor on Dog which takes another dog as argument.

    Clone method[1]:

    List<Dog> clonedDogs = dogs.stream().map(d -> d.clone()).collect(toList());
    

    Getting an ArrayList as the result

    Or, if you have to get an ArrayList back (in case you want to modify it later):

    ArrayList<Dog> clonedDogs = dogs.stream().map(Dog::new).collect(toCollection(ArrayList::new));
    

    Update the list in place

    If you don't need to keep the original content of the dogs list you can instead use the replaceAll method and update the list in place:

    dogs.replaceAll(Dog::new);
    

    All examples assume import static java.util.stream.Collectors.*;.


    Collector for ArrayLists

    The collector from the last example can be made into a util method. Since this is such a common thing to do I personally like it to be short and pretty. Like this:

    ArrayList<Dog> clonedDogs = dogs.stream().map(d -> d.clone()).collect(toArrayList());
    
    public static <T> Collector<T, ?, ArrayList<T>> toArrayList() {
        return Collectors.toCollection(ArrayList::new);
    }
    

    [1] Note on CloneNotSupportedException:

    For this solution to work the clone method of Dog must not declare that it throws CloneNotSupportedException. The reason is that the argument to map is not allowed to throw any checked exceptions.

    Like this:

        // Note: Method is public and returns Dog, not Object
        @Override
        public Dog clone() /* Note: No throws clause here */ { ...
    

    This should not be a big problem however, since that is the best practice anyway. (Effectice Java for example gives this advice.)

    Thanks to Gustavo for noting this.


    PS:

    If you find it prettier you can instead use the method reference syntax to do exactly the same thing:

    List<Dog> clonedDogs = dogs.stream().map(Dog::clone).collect(toList());
    
    0 讨论(0)
提交回复
热议问题