วิธีการโคลน ArrayList และการโคลนเนื้อหาได้อย่างไร


273

ฉันจะโคลนArrayListและโคลนรายการใน Java ได้อย่างไร

เช่นฉันมี:

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

และฉันคาดหวังว่าวัตถุในclonedListนั้นจะไม่เหมือนกับรายการสุนัข


มันได้รับการกล่าวถึงอยู่ในโคลนลึกยูทิลิตี้แนะนำเพลงคำถาม
Swiety

คำตอบ:


199

คุณจะต้องวนซ้ำในไอเท็มและทำการโคลนนิ่งทีละตัววางโคลนนิ่งในอาร์เรย์ผลลัพธ์ของคุณในขณะที่คุณไป

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()เมธอด


19
คุณไม่สามารถทำมันได้โดยทั่วไป clone () ไม่ได้เป็นส่วนหนึ่งของส่วนต่อประสาน Cloneable
Michael Myers

13
แต่โคลน () ได้รับการคุ้มครองในวัตถุดังนั้นคุณจึงไม่สามารถเข้าถึงได้ ลองรวบรวมรหัสนั้น
Michael Myers

5
ชั้นเรียนทั้งหมดขยายวัตถุเพื่อให้พวกเขาสามารถแทนที่โคลน () นี่คือสิ่งที่ Cloneable มีไว้สำหรับ!
Stephan202

2
นี่เป็นคำตอบที่ดี Cloneable เป็นอินเทอร์เฟซจริง อย่างไรก็ตาม mmyers มีจุดซึ่งวิธีการโคลน () เป็นวิธีการป้องกันที่ประกาศในคลาสวัตถุ คุณจะต้องแทนที่วิธีนี้ในคลาส Dog ของคุณและทำการคัดลอกฟิลด์ด้วยตัวเอง
Jose

3
ฉันพูดสร้างโรงงานหรือผู้สร้างหรือเพียงแค่วิธีคงที่ที่จะใช้อินสแตนซ์ของ Dog และคัดลอกฟิลด์ด้วยตนเองไปยังอินสแตนซ์ใหม่และคืนอินสแตนซ์ใหม่นั้น
Jose

196

โดยส่วนตัวแล้วฉันจะเพิ่มนวกรรมิกใน Dog:

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

    public Dog(Dog dog) {
        // Copy all the fields of Dog.
    }
}

จากนั้นแค่ทำซ้ำ (ดังแสดงในคำตอบของ Varkhan):

public static List<Dog> cloneList(List<Dog> dogList) {
    List<Dog> clonedList = new ArrayList<Dog>(dogList.size());
    for (Dog dog : dogList) {
        clonedList.add(new Dog(dog));
    }
    return clonedList;
}

ฉันพบว่าข้อดีของสิ่งนี้คือคุณไม่จำเป็นต้องไปไหนมาไหนกับสิ่งที่ Cloneable ใน Java นอกจากนี้ยังตรงกับวิธีที่คุณคัดลอกคอลเลกชัน Java

ตัวเลือกอื่นอาจเป็นการเขียนส่วนต่อประสาน ICloneable ของคุณเองและใช้สิ่งนั้น ด้วยวิธีนี้คุณสามารถเขียนวิธีทั่วไปสำหรับการโคลน


คุณจะเจาะจงมากขึ้นด้วยการคัดลอกฟิลด์ทั้งหมดของ DOG ฉันไม่เข้าใจจริงๆ :(
ดร. aNdRO

เป็นไปได้ไหมที่จะเขียนฟังก์ชั่นนั้นสำหรับวัตถุที่ไม่ได้กำหนด (แทน Dog)?
Tobi G.

@TobiG ฉันไม่เข้าใจว่าคุณหมายถึงอะไร คุณต้องการcloneList(List<Object>)หรือDog(Object)?
cdmckay

@cdmckay One Function ที่ใช้สำหรับ cloneList (List <Object>), cloneList (List <Dog>) และ cloneList (List <Cat>) แต่คุณไม่สามารถเรียกผู้สร้างทั่วไปฉันเดาว่า ... ?
Tobi G.

@TobiG เช่นเดียวกับฟังก์ชั่นการโคลนนิ่งทั่วไปใช่ไหม นั่นไม่ใช่สิ่งที่คำถามนี้เกี่ยวกับ
cdmckay

143

คอลเลกชันมาตรฐานทั้งหมดมีตัวสร้างสำเนา ใช้มัน.

List<Double> original = // some list
List<Double> copy = new ArrayList<Double>(original); //This does a shallow copy

clone()ได้รับการออกแบบโดยมีข้อผิดพลาดหลายประการ (ดูคำถามนี้ ) ดังนั้นจึงเป็นการดีที่สุดที่จะหลีกเลี่ยง

จากEffective Java 2nd Edition , Item 11: Override clone อย่างรอบคอบ

เนื่องจากปัญหาทั้งหมดที่เกี่ยวข้องกับ Cloneable นั้นปลอดภัยที่จะกล่าวว่าอินเทอร์เฟซอื่นไม่ควรขยายและคลาสที่ออกแบบมาสำหรับการสืบทอด (รายการที่ 17) ไม่ควรนำมาใช้ เนื่องจากข้อบกพร่องจำนวนมากโปรแกรมเมอร์ผู้เชี่ยวชาญบางคนก็เลือกที่จะไม่แทนที่วิธีการโคลนและไม่เรียกมันยกเว้นบางทีเพื่อคัดลอกอาร์เรย์ หากคุณออกแบบคลาสสำหรับการสืบทอดโปรดทราบว่าหากคุณเลือกที่จะไม่ให้วิธีการโคลนที่มีการป้องกันอย่างดีมันจะเป็นไปไม่ได้ที่คลาสย่อยจะใช้ Cloneable

หนังสือเล่มนี้ยังอธิบายถึงข้อดีของการสร้างสำเนาที่มีมากกว่า Cloneable / clone

  • พวกเขาไม่ต้องพึ่งพากลไกการสร้างวัตถุ extralinguistic ที่มีความเสี่ยง
  • พวกเขาไม่ต้องการการยึดมั่นที่จะบังคับใช้กับอนุสัญญาที่จัดทำเอกสารบาง ๆ
  • พวกเขาไม่ได้ขัดแย้งกับการใช้งานที่เหมาะสมของเขตข้อมูลสุดท้าย
  • พวกเขาไม่โยนข้อยกเว้นการตรวจสอบที่ไม่จำเป็น
  • พวกเขาไม่ต้องการปลดเปลื้อง

พิจารณาประโยชน์ของการใช้การก่อสร้างสำเนาอื่น: สมมติว่าคุณมีและคุณต้องการคัดลอกเป็นHashSet s TreeSetวิธีโคลนไม่สามารถนำเสนอฟังก์ชั่นนี้ new TreeSet(s)แต่มันเป็นเรื่องง่ายด้วยตัวสร้างแปลง:


85
เท่าที่ฉันทราบตัวสร้างสำเนาของคอลเลกชันมาตรฐานสร้างสำเนาตื้นไม่ใช่สำเนาลึก คำถามที่ถามที่นี่มองหาคำตอบที่คัดลอกลึก
Abdull

20
สิ่งนี้ผิดปกติเพียงแค่คัดลอก constuctors ทำสำเนาตื้น - whoint epoint ของคำถาม te
NimChimpsky

1
สิ่งที่ถูกต้องเกี่ยวกับคำตอบนี้คือหากคุณไม่ได้กลายพันธุ์วัตถุในรายการการเพิ่มหรือลบรายการจะไม่ลบสิ่งเหล่านั้นออกจากรายการทั้งสอง มันไม่ได้เป็นตื้นเป็นที่ได้รับมอบหมายที่เรียบง่าย
Noumenon

42

Java 8 มีวิธีการใหม่ที่จะเรียกตัวสร้างสำเนาหรือวิธีการโคลนสุนัของค์ประกอบอย่างหรูหราและดาน: Streams , lambdasและนักสะสม

คัดลอกคอนสตรัค:

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

การแสดงออกDog::newที่เรียกว่าการอ้างอิงวิธี มันสร้างฟังก์ชั่นวัตถุที่เรียกคอนสตรัคเตอร์Dogซึ่งใช้สุนัขตัวอื่นเป็นอาร์กิวเมนต์

วิธีการโคลน [1]:

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

ได้รับArrayListผลที่ตามมา

หรือถ้าคุณต้องรับArrayListกลับ (ในกรณีที่คุณต้องการแก้ไขในภายหลัง):

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

อัปเดตรายการในสถานที่

หากคุณไม่จำเป็นต้องเก็บเนื้อหาดั้งเดิมของdogsรายการไว้คุณสามารถใช้replaceAllวิธีการและอัปเดตรายการแทน

dogs.replaceAll(Dog::new);

import static java.util.stream.Collectors.*;ตัวอย่างทั้งหมดถือว่า


สะสมสำหรับArrayLists

ตัวรวบรวมจากตัวอย่างล่าสุดสามารถทำเป็นวิธีใช้ได้ เนื่องจากนี่เป็นสิ่งที่ธรรมดามากที่ฉันจะทำเองสั้นและสวย แบบนี้:

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] หมายเหตุเกี่ยวกับCloneNotSupportedException:

สำหรับการแก้ปัญหานี้ในการทำงานcloneวิธีการDog ไม่ต้องCloneNotSupportedExceptionประกาศว่ามันจะพ่น เหตุผลคืออาร์กิวเมนต์mapไม่ได้รับอนุญาตให้โยนข้อยกเว้นที่ตรวจสอบแล้ว

แบบนี้:

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

นี่ไม่ควรเป็นปัญหาใหญ่เพราะเป็นวิธีปฏิบัติที่ดีที่สุดอยู่ดี ( เช่น Effectice Javaให้คำแนะนำนี้)

ขอบคุณ Gustavo ที่สังเกตสิ่งนี้


PS:

หากคุณพบว่าน่าสนใจคุณสามารถใช้ไวยากรณ์การอ้างอิงเมธอดแทนเพื่อทำสิ่งเดียวกัน:

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

คุณเห็นผลกระทบของการทำงานในลักษณะที่สุนัข (d) เป็นตัวสร้างสำเนาหรือไม่? List<Dog> clonedDogs = new ArrayList<>(); dogs.stream().parallel().forEach(d -> clonedDogs.add(new Dog(d)));
SaurabhJinturkar

1
@SaurabhJinturkar: เวอร์ชันของคุณไม่ปลอดภัยสำหรับเธรดและไม่ควรใช้กับสตรีมแบบขนาน นั่นเป็นเพราะการparallelโทรทำให้clonedDogs.addถูกเรียกจากหลายเธรดในเวลาเดียวกัน เวอร์ชันที่ใช้collectนั้นปลอดภัยต่อเธรด นี่เป็นหนึ่งในข้อดีของฟังก์ชั่นการทำงานของไลบรารี่ไลบรารี่สามารถใช้โค้ดเดียวกันสำหรับสตรีมแบบขนาน
Lii

1
@SaurabhJinturkar: นอกจากนี้การดำเนินการรวบรวมยังเป็นไปอย่างรวดเร็ว มันเหมือนกันกับเวอร์ชั่นของคุณ แต่ก็ใช้ได้กับสตรีมแบบขนาน คุณสามารถแก้ไขเวอร์ชันของคุณโดยใช้ตัวอย่างเช่นคิวที่เกิดขึ้นพร้อมกันแทนที่จะเป็นรายการอาร์เรย์ แต่ฉันเกือบแน่ใจว่ามันจะช้ากว่ามาก
Lii

เมื่อใดก็ตามที่ฉันพยายามที่จะใช้วิธีการแก้ปัญหาของคุณฉันได้รับในUnhandled exception type CloneNotSupportedException d.clone()การประกาศข้อยกเว้นหรือการจับไม่ได้ช่วยแก้ปัญหา
Gustavo

@Gustavo: เกือบจะแน่นอนเพราะวัตถุที่คุณโคลน ( Dogในตัวอย่างนี้) ไม่รองรับการโคลน คุณแน่ใจหรือว่าใช้Clonableอินเทอร์เฟซได้
Lii

28

โดยทั่วไปมีสามวิธีโดยไม่ต้องวนซ้ำด้วยตนเอง

1 ใช้ตัวสร้าง

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

2 การใช้ addAll(Collection<? extends E> c)

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

3 ใช้addAll(int index, Collection<? extends E> c)วิธีการที่มีintพารามิเตอร์

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

หมายเหตุ: พฤติกรรมของการดำเนินการเหล่านี้จะไม่ได้กำหนดหากมีการแก้ไขการรวบรวมที่ระบุในขณะที่การดำเนินการอยู่ในระหว่างดำเนินการ


50
โปรดอย่าว่าตัวแปรทั้งสามนี้สร้างเพียงสำเนาของรายการเท่านั้น
electrobabe

9
นี่ไม่ใช่การโคลนแบบลึกรายการทั้งสองนั้นเก็บวัตถุเดียวกันเอาไว้คัดลอกข้อมูลอ้างอิงเท่านั้น แต่วัตถุ Dog เมื่อคุณแก้ไขรายการใดรายการหนึ่งรายการถัดไปจะมีการเปลี่ยนแปลงแบบเดียวกัน ดอนนี่ไม่ชอบ upvotes มากมาย
Saorikido

1
@ Neeson.Z วิธีการทั้งหมดจะสร้างสำเนาลึกของรายการและสำเนาตื้นขององค์ประกอบของรายการ หากคุณปรับเปลี่ยนองค์ประกอบของรายการการเปลี่ยนแปลงจะมีผลกับรายการอื่น แต่ถ้าคุณแก้ไขรายการใดรายการหนึ่ง (เช่นลบวัตถุ) รายการอื่นจะไม่เปลี่ยนแปลง
Alessandro Teruzzi

17

ฉันคิดว่าคำตอบสีเขียวปัจจุบันไม่ดีทำไมคุณอาจถาม

  • มันอาจจำเป็นต้องเพิ่มรหัสจำนวนมาก
  • มันต้องการให้คุณแสดงรายการทั้งหมดที่จะคัดลอกและทำสิ่งนี้

วิธีการทำให้เป็นอันดับเป็น imo ไม่ดีคุณอาจต้องเพิ่ม Serializable ให้ทั่ว

ดังนั้นทางออกคืออะไร:

ไลบรารี Java Deep-Cloning ไลบรารี โคลนเป็นไลบรารี java ขนาดเล็กแบบโอเพ่นซอร์ส (apache license) ซึ่งเป็นวัตถุโคลนนิ่งลึก วัตถุไม่จำเป็นต้องใช้ส่วนต่อประสาน Cloneable Effectivelly ห้องสมุดนี้สามารถโคลนวัตถุ java ใด ๆ สามารถใช้งานได้เช่นในการปรับใช้แคชหากคุณไม่ต้องการให้วัตถุแคชถูกแก้ไขหรือเมื่อใดก็ตามที่คุณต้องการสร้างสำเนาวัตถุ

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

ตรวจสอบได้ที่https://github.com/kostaskougios/cloning


8
ข้อแม้หนึ่งที่ใช้วิธีนี้คือใช้การสะท้อนซึ่งอาจช้ากว่าโซลูชันของ Varkhan ค่อนข้างเล็กน้อย
cdmckay

6
ฉันไม่เข้าใจจุดแรก "ต้องใช้รหัสมาก" ห้องสมุดที่คุณกำลังพูดถึงจะต้องใช้รหัสเพิ่มเติม เป็นเพียงเรื่องของการที่คุณวางมัน มิฉะนั้นผมเห็นห้องสมุดที่พิเศษสำหรับชนิดของสิ่งนี้จะช่วยให้ ..
Nawfal

8

ฉันพบวิธีคุณสามารถใช้ json เพื่อทำให้เป็นอนุกรม / unserialize รายการ รายการต่อเนื่องไม่มีการอ้างอิงไปยังวัตถุต้นฉบับเมื่อไม่ได้ระบุ

ใช้ gson:

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());

คุณสามารถทำได้โดยใช้แจ็คสันและห้องสมุด json อื่น ๆ ด้วย


1
ฉันไม่รู้ว่าทำไมผู้คนถึงปฏิเสธคำตอบนี้ คำตอบอื่น ๆ จะต้องใช้การโคลน () หรือต้องเปลี่ยนการพึ่งพาเพื่อรวมไลบรารีใหม่ แต่ห้องสมุด JSon ส่วนใหญ่ของโครงการจะรวมอยู่แล้ว ฉัน upvoting สำหรับสิ่งนี้
Satish

1
@Satish ใช่นี่เป็นคำตอบเดียวที่ช่วยฉันฉันไม่แน่ใจว่ามีอะไรผิดปกติกับคนอื่น ๆ แต่ไม่ว่าฉันจะทำอะไรลอกแบบหรือใช้ตัวสร้างสำเนารายการเดิมของฉันที่ใช้เพื่อรับการปรับปรุง แต่ด้วยวิธีนี้ ดังนั้นขอขอบคุณผู้เขียน!
Parag Pawar

มันเป็นความจริงที่ไม่ใช่คำตอบของจาวาที่บริสุทธิ์สำหรับความรู้ แต่เป็นวิธีแก้ปัญหาที่มีประสิทธิภาพในการจัดการกับปัญหานี้อย่างรวดเร็ว
marcRDZ

แฮ็คที่ดีประหยัดเวลาได้มาก
mxml

6

ฉันใช้ตัวเลือกนี้เสมอ:

ArrayList<Dog> clonedList = new ArrayList<Dog>(name_of_arraylist_that_you_need_to_Clone);

2

คุณจะต้องโคลนArrayListด้วยมือ (โดยวนซ้ำและคัดลอกแต่ละองค์ประกอบไปยังองค์ประกอบใหม่ArrayList) เพราะclone()จะไม่ทำเพื่อคุณ เหตุผลสำหรับสิ่งนี้คือวัตถุที่มีอยู่ในArrayListอาจไม่ใช้งานClonableเอง

แก้ไข : ... และนั่นคือสิ่งที่รหัสของ Varkhan ทำ


1
และถึงแม้ว่าพวกเขาจะทำไม่มีวิธีเข้าถึง clone () นอกเหนือจากการสะท้อนและไม่รับประกันว่าจะประสบความสำเร็จ
Michael Myers

1

วิธีที่น่ารังเกียจคือการทำด้วยการสะท้อน บางอย่างเช่นนี้ใช้ได้สำหรับฉัน

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

เคล็ดลับเรียบร้อยและน่ารังเกียจ! ปัญหาที่อาจเกิดขึ้นหนึ่ง: หากoriginalมีวัตถุของคลาสที่แตกต่างกันฉันคิดว่าcloneMethod.invokeจะล้มเหลวโดยมีข้อยกเว้นเมื่อมีการเรียกใช้ด้วยวัตถุชนิดที่ไม่ถูกต้อง ด้วยเหตุนี้จึงเป็นการดีกว่าที่จะดึงโคลนเฉพาะMethodสำหรับแต่ละวัตถุ หรือใช้วิธีการโคลนบนObject(แต่เนื่องจากมีการป้องกันที่อาจล้มเหลวในกรณีอื่น ๆ )
Lii

นอกจากนี้ฉันคิดว่ามันจะดีกว่าที่จะโยนข้อยกเว้นรันไทม์ใน catch-clause แทนที่จะกลับรายการว่างเปล่า
Lii

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

นี่จะคัดลอกสุนัขแต่ละตัวอย่างลึกซึ้ง


0

ผู้โพสต์อื่นถูกต้อง: คุณต้องวนซ้ำรายการและคัดลอกไปยังรายการใหม่

อย่างไรก็ตาม ... หากวัตถุในรายการไม่สามารถเปลี่ยนแปลงได้ - คุณไม่จำเป็นต้องทำการโคลน หากวัตถุของคุณมีกราฟวัตถุที่ซับซ้อนพวกเขาจะต้องไม่เปลี่ยนรูปเช่นกัน

ประโยชน์อื่น ๆ ของการเปลี่ยนรูปไม่ได้ก็คือพวกมันมีความปลอดภัยเช่นกัน


0

นี่คือวิธีแก้ไขโดยใช้ประเภทเทมเพลตทั่วไป:

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

ยาชื่อสามัญนั้นดี แต่คุณต้องโคลนรายการเพื่อตอบคำถาม ดูstackoverflow.com/a/715660/80425
David Snabel-Caunt

0

สำหรับคุณวัตถุแทนที่โคลน () วิธีการ

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

และโทร. clone () สำหรับ Vector obj หรือ ArraiList obj ....


0

วิธีง่ายๆโดยใช้ commons-lang-2.3.jar ไลบรารีของ java ไปยังรายการโคลน

ลิงค์ดาวน์โหลด commons-lang-2.3.jar

วิธีใช้

oldList.........
List<YourObject> newList = new ArrayList<YourObject>();
foreach(YourObject obj : oldList){
   newList.add((YourObject)SerializationUtils.clone(obj));
}

ฉันหวังว่าอันนี้จะมีประโยชน์

: D


1
เพิ่งทราบ: เหตุใดจึงเป็นคอมมอนส์รุ่นเก่าเช่นนี้ ดูประวัติการวางจำหน่ายได้ที่นี่: commons.apache.org/proper/commons-lang/release-history.html
informatik01

0

แพคเกจ import org.apache.commons.lang.SerializationUtils;

มีวิธีการคือ SerializationUtils.clone(Object);

ตัวอย่าง

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

ล้าสมัยเล็กน้อยเพื่อตอบคำถามนี้ และคำตอบอื่น ๆ อีกมากมายในความคิดเห็นด้านล่างคำถาม
moskito-x

0

ฉันเพิ่งพัฒนา lib ที่สามารถโคลนเอนทิตีวัตถุและวัตถุ java.util.List เพียงดาวน์โหลด jar ในhttps://drive.google.com/open?id=0B69Sui5ah93EUTloSktFUkctN0Uและใช้ cloneListObject (รายการรายการ) วิธีนี้ไม่เพียง แต่โคลนรายการ แต่ยังรวมถึงองค์ประกอบเอนทิตีทั้งหมด


0

ด้านล่างใช้งานได้สำหรับฉัน ..

ใน Dog.java

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

นี่คือรายการใหม่ที่สร้างขึ้นจากเมธอด createCopy ถูกสร้างผ่าน SerializationUtils.clone () ดังนั้นการเปลี่ยนแปลงใด ๆ ที่เกิดขึ้นกับรายการใหม่จะไม่มีผลกับรายการต้นฉบับ


-1

ฉันคิดว่าฉันพบวิธีที่ง่ายมากในการทำ ArrayList ที่เป็นสำเนา สมมติว่าคุณต้องการคัดลอก String ArrayList arrayA

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

แจ้งให้เราทราบหากไม่ได้ผลสำหรับคุณ


3
ไม่ทำงานหากคุณใช้รายการ <List <JsonObject>> ในกรณีของฉัน
djdance

เงื่อนไขไม่เปลี่ยนรูป การโคลนนิ่งไม่สมเหตุสมผลและในตัวอย่าง arrayB และ arrayA ของคุณมีการอ้างอิงวัตถุเดียวกัน - สำเนาตื้น ๆ
Christian Fries
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.