ฉันมีสิ่งArrayList<String>
ที่ฉันต้องการคืนสำเนา ArrayList
มีวิธีการโคลนซึ่งมีลายเซ็นดังต่อไปนี้:
public Object clone()
หลังจากที่ฉันเรียกเมธอดนี้ฉันจะเหวี่ยง Object ที่ส่งคืนกลับไปได้ArrayList<String>
อย่างไร
ฉันมีสิ่งArrayList<String>
ที่ฉันต้องการคืนสำเนา ArrayList
มีวิธีการโคลนซึ่งมีลายเซ็นดังต่อไปนี้:
public Object clone()
หลังจากที่ฉันเรียกเมธอดนี้ฉันจะเหวี่ยง Object ที่ส่งคืนกลับไปได้ArrayList<String>
อย่างไร
คำตอบ:
ArrayList newArrayList = (ArrayList) oldArrayList.clone();
ArrayList<String> newArrayList = (ArrayList<String>) oldArrayList.clone();
คุณดีกว่าการใช้
List<String>
แทนArrayList<String>
ทางด้านซ้าย นี่คือวิธีการใช้คอลเลกชันเกือบตลอดเวลา
ทำไมคุณต้องการโคลน การสร้างรายการใหม่มักจะเหมาะสมกว่า
List<String> strs;
...
List<String> newStrs = new ArrayList<>(strs);
งานเสร็จแล้ว
ArrayList(Collection<? extends E> c)
ความหมายว่ามันไม่สำคัญว่าคุณใช้รายการประเภทใดเป็นอาร์กิวเมนต์
นี่คือรหัสที่ฉันใช้:
ArrayList copy = new ArrayList (original.size());
Collections.copy(copy, original);
หวังว่าจะเป็นประโยชน์สำหรับคุณ
ArrayList
ใช้ArrayList<YourObject>
ArrayList
นวกรรมิก?
ด้วย Java 8 มันสามารถโคลนกับกระแส
import static java.util.stream.Collectors.toList;
...
List<AnObject> clone = myList.stream().collect(toList());
toCollection
อาจเป็นทางเลือกที่ดีกว่า
โปรดทราบว่า Object.clone () มีปัญหาที่สำคัญบางประการและการใช้งานนั้นไม่ได้รับการสนับสนุนในกรณีส่วนใหญ่ โปรดดูรายการที่ 11 จาก " Java ที่มีประสิทธิภาพ " โดย Joshua Bloch สำหรับคำตอบที่สมบูรณ์ ฉันเชื่อว่าคุณสามารถใช้ Object.clone () ในอาร์เรย์ประเภทดั้งเดิมได้อย่างปลอดภัย แต่นอกเหนือจากนั้นคุณจะต้องมีความรอบคอบในการใช้และการแทนที่โคลนอย่างถูกต้อง คุณน่าจะดีกว่าการกำหนดตัวสร้างการคัดลอกหรือวิธีการโรงงานคงที่ชัดเจนโคลนวัตถุตามความหมายของคุณ
ฉันคิดว่านี่น่าจะเป็นเคล็ดลับที่ใช้ Collections API:
หมายเหตุ : วิธีการคัดลอกทำงานในเวลาเชิงเส้น
//assume oldList exists and has data in it.
List<String> newList = new ArrayList<String>();
Collections.copy(newList, oldList);
List<MySerializableObject> copyList = new ArrayList<>(mMySerializableObjects.size());
ดูเหมือนว่าการใช้copyList.addAll(original);
เป็นทางเลือกที่ดี
int
ขัดแย้งลึกลับ addAll
ผมเคยคิดว่าทำไมคุณต้องการที่จะใช้วิธีการนี้คงปิดบังแทนดีเก่า
ฉันพบว่าการใช้ addAll ใช้งานได้ดี
ArrayList<String> copy = new ArrayList<String>();
copy.addAll(original);
วงเล็บถูกใช้มากกว่าไวยากรณ์ทั่วไป
new ArrayList<String>(original)
?
ถ้าคุณต้องการสิ่งนี้เพื่อที่จะสามารถคืนค่า List ใน getter มันจะดีกว่าถ้าทำ:
ImmutableList.copyOf(list);
หากต้องการโคลนอินเทอร์เฟซทั่วไปอย่างjava.util.List
คุณจะต้องส่งมัน นี่คือตัวอย่าง:
List list = new ArrayList();
List list2 = ((List) ( (ArrayList) list).clone());
มันค่อนข้างยุ่งยาก แต่ใช้งานได้ถ้าคุณถูก จำกัด ให้ส่งคืนList
อินเทอร์เฟซดังนั้นใครก็ตามหลังจากคุณสามารถใช้รายการของคุณได้ทุกเมื่อที่เขาต้องการ
ฉันรู้ว่าคำตอบนี้อยู่ใกล้กับคำตอบสุดท้าย แต่คำตอบของฉันตอบว่าจะทำอย่างไรในขณะที่คุณทำงานกับList
- ผู้ปกครองทั่วไป - ไม่ArrayList
ระวังตัวมากเมื่อทำการโคลน ArrayLists การโคลนนิ่งใน java เป็นแบบตื้น นี่หมายความว่ามันจะโคลน Arraylist เท่านั้นเองและไม่ใช่สมาชิกของ Arraylist ดังนั้นหากคุณมี ArrayList X1 และโคลนลงใน X2 การเปลี่ยนแปลงใด ๆ ใน X2 ก็จะปรากฏใน X1 และในทางกลับกัน เมื่อคุณโคลนคุณจะสร้าง ArrayList ใหม่ที่มีตัวชี้ไปยังองค์ประกอบเดียวกันในต้นฉบับ
สิ่งนี้ควรใช้:
ArrayList<String> orig = new ArrayList<String>();
ArrayList<String> copy = (ArrayList<String>) orig.clone()
List<String> shallowClonedList = new ArrayList<>(listOfStrings);
โปรดจำไว้ว่านี่เป็นเพียงสำเนาตื้น ๆ เท่านั้น คุณได้รับรายการใหม่ แต่รายการเหมือนกัน นี่ไม่ใช่ปัญหาสำหรับสตริงเพียงอย่างเดียว รับยุ่งยากมากขึ้นเมื่อรายการรายการเป็นวัตถุเอง
ArrayList first = new ArrayList ();
ArrayList copy = (ArrayList) first.clone ();
ฉันไม่ใช่จาวามืออาชีพ แต่ฉันมีปัญหาเดียวกันและฉันพยายามแก้ไขด้วยวิธีนี้ (สมมติว่า T มีตัวสร้างสำเนา)
public static <T extends Object> List<T> clone(List<T> list) {
try {
List<T> c = list.getClass().newInstance();
for(T t: list) {
T copy = (T) t.getClass().getDeclaredConstructor(t.getclass()).newInstance(t);
c.add(copy);
}
return c;
} catch(Exception e) {
throw new RuntimeException("List cloning unsupported",e);
}
}
List
คลาสการใช้งานจะมีตัวสร้างแบบไม่มีอาร์กิวเมนต์แบบสาธารณะ ยกตัวอย่างเช่นList
s ผลตอบแทนโดยArray.asList
, List.of
หรือList.subList
อาจจะทำไม่ได้