Jak mogę sklonować, ArrayList
a także sklonować jego elementy w Javie?
Na przykład mam:
ArrayList<Dog> dogs = getDogs();
ArrayList<Dog> clonedList = ....something to do with dogs....
I spodziewałbym się, że obiekty w clonedList
nie są takie same jak na liście psów.
java
collections
clone
deep-copy
palig
źródło
źródło
Odpowiedzi:
Będziesz musiał iterować przedmioty i klonować je jeden po drugim, umieszczając klony w tablicy wyników w miarę upływu czasu.
Aby to zadziałało, oczywiście będziesz musiał poprosić
Dog
klasę o wdrożenieCloneable
interfejsu i zastąpienieclone()
metody.źródło
Osobiście dodałbym konstruktora do Dog:
Następnie wystarczy powtórzyć (jak pokazano w odpowiedzi Varkhana):
Zaletą tego jest to, że nie musisz grzebać w zepsutych plikach do klonowania w Javie. Pasuje również do sposobu kopiowania kolekcji Java.
Inną opcją może być napisanie własnego interfejsu ICloneable i użycie go. W ten sposób możesz napisać ogólną metodę klonowania.
źródło
cloneList(List<Object>)
czyDog(Object)
?Wszystkie standardowe kolekcje mają konstruktory kopii. Użyj ich.
clone()
został zaprojektowany z kilkoma błędami (patrz to pytanie ), więc najlepiej go unikać.Z Effective Java 2nd Edition , pozycja 11: Zastąp klon ostrożnie
Ta książka opisuje także wiele zalet konstruktorów kopiowania w stosunku do Cloneable / clone.
Rozważ kolejną zaletę korzystania z konstruktorów kopiowania: Załóżmy, że masz plik
HashSet s
i chcesz go skopiować jako plikTreeSet
. Metoda clone nie oferuje tej funkcji, ale jest to łatwe z konstruktora konwersji:new TreeSet(s)
.źródło
Java 8 zapewnia nowy sposób wywoływania metody konstruktora kopiowania lub metody klonowania na psach elementu w elegancki i kompaktowy sposób: strumieni , lambd i kolektorów .
Kopiuj konstruktor:
Wyrażenie
Dog::new
to nazywa się odwołaniem do metody . Tworzy obiekt funkcyjny, który wywołuje konstruktor,Dog
który przyjmuje argument innego psa.Metoda klonowania [1]:
Uzyskanie
ArrayList
w wynikuLub, jeśli musisz uzyskać
ArrayList
zwrot (na wypadek, gdybyś chciał go później zmodyfikować):Zaktualizuj listę na miejscu
Jeśli nie musisz zachowywać oryginalnej zawartości
dogs
listy, możesz zamiast tego użyćreplaceAll
metody i zaktualizować listę w miejscu:Wszystkie przykłady zakładają
import static java.util.stream.Collectors.*;
.Kolektor dla
ArrayList
sKolektor z ostatniego przykładu można przekształcić w metodę util. Ponieważ jest to tak powszechna rzecz, osobiście podoba mi się, że jest krótka i ładna. Lubię to:
[1] Uwaga
CloneNotSupportedException
:Aby to rozwiązanie zadziałało,
clone
metodaDog
nie może deklarować, że wyrzucaCloneNotSupportedException
. Powodem jest to, że argument domap
nie może generować sprawdzonych wyjątków.Lubię to:
Nie powinno to jednak stanowić dużego problemu, ponieważ i tak jest to najlepsza praktyka. ( Na przykład Java Java Effectice daje taką radę).
Dzięki Gustavo za zwrócenie uwagi na to.
PS:
Jeśli uważasz, że jest ładniejsza, możesz zamiast tego użyć składni odwołania do metody, aby zrobić dokładnie to samo:
źródło
List<Dog> clonedDogs = new ArrayList<>(); dogs.stream().parallel().forEach(d -> clonedDogs.add(new Dog(d)));
parallel
wywołanie powoduje, żeclonedDogs.add
wywoływane jest z wielu wątków jednocześnie. Wersje, których używa,collect
są bezpieczne dla wątków. Jest to jedna z zalet funkcjonalnego modelu biblioteki strumieni, ten sam kod może być użyty dla równoległych strumieni.Unhandled exception type CloneNotSupportedException
na to wpływd.clone()
. Zadeklarowanie wyjątku lub wyłapanie go nie rozwiązuje problemu.Dog
w tym przykładzie) nie obsługuje klonowania. Czy jesteś pewien, że implementujeClonable
interfejs?Zasadniczo istnieją trzy sposoby bez ręcznego powtarzania,
1 Korzystanie z konstruktora
2 Korzystanie
addAll(Collection<? extends E> c)
3 Używanie
addAll(int index, Collection<? extends E> c)
metody zint
parametremUwaga: Zachowanie tych operacji będzie niezdefiniowane, jeśli określony zbiór zostanie zmodyfikowany podczas operacji.
źródło
Myślę, że obecna zielona odpowiedź jest zła , dlaczego możesz zapytać?
Sposób serializacji jest również zły imo, być może będziesz musiał dodać Serializable w dowolnym miejscu.
Więc jakie jest rozwiązanie:
Biblioteka głębokiego klonowania Java Biblioteka klonowania jest małą biblioteką Java typu open source (licencja Apache), która głęboko klonuje obiekty. Obiekty nie muszą implementować interfejsu klonowalnego. W rzeczywistości ta biblioteka może klonować KAŻDE obiekty Java. Może być stosowany np. W implementacjach pamięci podręcznej, jeśli nie chcesz, aby buforowany obiekt był modyfikowany lub gdy chcesz utworzyć głęboką kopię obiektów.
Sprawdź to na https://github.com/kostaskougios/cloning
źródło
Znalazłem sposób, możesz użyć json do serializacji / odserializowania listy. Serializowana lista nie zawiera odniesienia do oryginalnego obiektu, gdy nie jest serializowana.
Korzystanie z gson:
Możesz to zrobić za pomocą Jacksona i dowolnej innej biblioteki json.
źródło
Zawsze korzystałem z tej opcji:
źródło
Będziesz musiał
ArrayList
ręcznie sklonować (poprzez iterację nad nim i skopiowanie każdego elementu do nowegoArrayList
), ponieważclone()
nie zrobi to za ciebie. Powodem tego jest to, że obiekty znajdujące się wArrayList
nie może realizowaćClonable
siebie.Edycja : ... i dokładnie to robi kod Varkhana.
źródło
Paskudnym sposobem jest zrobienie tego za pomocą refleksji. Coś takiego działało dla mnie.
źródło
original
zawiera obiekty różnych klas, myślę,cloneMethod.invoke
że zawiedzie z wyjątkiem, gdy zostanie wywołany z niewłaściwym rodzajem obiektu. Z tego powodu może być lepiej pobrać określony klonMethod
dla każdego obiektu. Lub użyj metody klonowaniaObject
(ale ponieważ ta jest chroniona, może się nie powieść w większej liczbie przypadków).To głęboko skopiuje każdego psa
źródło
Pozostałe plakaty są poprawne: musisz powtórzyć listę i skopiować na nową listę.
Jednak ... Jeśli obiekty na liście są niezmienne - nie trzeba ich klonować. Jeśli twój obiekt ma złożony wykres obiektów - będą one również musiały być niezmienne.
Inną zaletą niezmienności jest to, że są one również wątkowo bezpieczne.
źródło
Oto rozwiązanie wykorzystujące ogólny typ szablonu:
źródło
dla ciebie obiekty zastępują metodę clone ()
i wywołaj .clone () dla Vector obj lub ArraiList obj ....
źródło
Łatwy sposób za pomocą commons-lang-2.3.jar tej biblioteki Java do klonowania listy
link pobierz commons-lang-2.3.jar
Jak używać
Mam nadzieję, że to może pomóc.
:RE
źródło
Paczka
import org.apache.commons.lang.SerializationUtils;
Istnieje metoda
SerializationUtils.clone(Object);
Przykład
źródło
Właśnie opracowałem bibliotekę, która jest w stanie sklonować obiekt encji i obiekt java.util.List. Wystarczy pobrać słoik na https://drive.google.com/open?id=0B69Sui5ah93EUTloSktFUkctN0U i użyć metody statycznej cloneListObject (lista list). Ta metoda nie tylko klonuje Listę, ale także wszystkie elementy encji.
źródło
Poniższe działało dla mnie ..
w Dog.java
Tutaj tworzona jest nowa lista utworzona za pomocą metody createCopy poprzez SerializationUtils.clone (). Tak więc wszelkie zmiany wprowadzone na nowej liście nie wpłyną na oryginalną listę
źródło
Myślę, że znalazłem naprawdę łatwy sposób na utworzenie głębokiej kopii ArrayList. Zakładając, że chcesz skopiować tablicę String ArrayListA.
Daj mi znać, jeśli to nie zadziała.
źródło