ArrayList.clear () และ ArrayList.removeAll () แตกต่างกันอย่างไร?


283

สมมติว่าarraylistมีการกำหนดเป็นArrayList<String> arraylistเป็นarraylist.removeAll(arraylist)เทียบเท่ากับarraylist.clear()?

ถ้าเป็นเช่นนั้นฉันสามารถสันนิษฐานได้ว่าclear()วิธีนี้มีประสิทธิภาพมากกว่าสำหรับการล้างรายการอาร์เรย์หรือไม่

มีข้อควรระวังในการใช้งานarraylist.removeAll(arraylist)แทนarraylist.clear()ไหม?


ข้อพิสูจน์ที่เป็นไปได้สำหรับคำถามนี้: เมื่อใดจึงควรใช้วิธีอื่นแทนคำตอบอื่น
Corey Ogburn

3
@Corey: เมื่อทุกคนอาจจะต้องการใช้arraylist.removeAll(arraylist)? ฉันไม่เห็นเหตุผลที่จะทำเช่นนั้น
โจอาคิมซาวเออร์

@Joachim Sauer นั่นคือสิ่งที่ฉันต้องการยืนยัน ขอบคุณ +2 แต่ความแตกต่างระหว่างelementData[i] = nullและที่e.remove()สำคัญคืออะไร?
ateiob

ไม่มีเหตุผลที่จะทำสติเป็นแทนarrList.removeAll(arrList) เป็นเรื่องที่แตกต่าง arrList.clear()arrList1.removeAll(arrList2)

3
หากการติดตั้ง removeAll เท่านั้น () เริ่มต้นด้วยบรรทัดนี้การสนทนาทั้งหมดนี้น่าจะสนุกมากขึ้น !!! if (c == this && !isEmpty()) { clear(); return true; }. ฉันจะต้องส่งสิ่งนี้ให้ OpenJDK เป็นแพทช์! ;-)
Julius Musseau

คำตอบ:


396

รหัสที่มาสำหรับclear():

public void clear() {
    modCount++;

    // Let gc do its work
    for (int i = 0; i < size; i++)
        elementData[i] = null;

    size = 0;
}

รหัสที่มาสำหรับremoveAll()(ตามที่กำหนดไว้ในAbstractCollection):

public boolean removeAll(Collection<?> c) {
    boolean modified = false;
    Iterator<?> e = iterator();
    while (e.hasNext()) {
        if (c.contains(e.next())) {
            e.remove();
            modified = true;
        }
    }
    return modified;
}

clear() เร็วกว่ามากเนื่องจากไม่ต้องจัดการกับการเรียกเมธอดพิเศษเหล่านั้นทั้งหมด

และดังที่ Atrey ชี้ให้เห็นc.contains(..)เพิ่มความซับซ้อนของเวลาในremoveAllการ O (n 2 ) เมื่อเทียบกับclear'O (n)


29
โปรดทราบว่าc.contains(...)กำลังสองความซับซ้อนของเวลาของการดำเนินการจะทำให้คำตอบนี้เสร็จสมบูรณ์
Atreys

8
แหล่งที่มามีความแข็งแกร่งในนี้ (สำหรับคำตอบอื่น ๆ ทั้งหมด: ใช้แหล่งที่มาลุค) สังเกตความชัดเจนว่าสามารถนำไปใช้งานได้อย่างไรเพียงแค่บรรทัดเดียวขนาด = 0; แต่การรวบรวมขยะไม่ทราบว่าจะรวบรวมองค์ประกอบในส่วนที่ไม่สามารถเข้าถึงได้ของอาร์เรย์
Julius Musseau

2
e.remove () ซับซ้อนกว่ากัน! e.remove () ยกกำลังสองให้ซับซ้อนเช่นเดียวกับ c.contain (... ) ใน ArrayList e.remove () จะเรียก ArrayList.remove (ดัชนี int) ซึ่งจะต้องเลื่อนส่วนที่เหลือของอาร์เรย์ไปทีละรายการ
Julius Musseau

1
@ateiob e.remove () เป็นการโทรพิเศษสองวิธีการตรวจสอบระยะไกลและการส่งคืนวัตถุ (ภายในถึงAbstractList.Itr.remove()และArrayList.remove(int)) เช่นกัน
Atreys

2
@julius ถ้าทำเช่นนี้: size = 0; elementData = new Object[10];ส่วนที่เหลือทั้งหมดจะถูกเก็บรวบรวมขยะเนื่องจากอาร์เรย์สำรองไม่มีการอ้างอิงภายนอก
corsiKa

51

ความซับซ้อนของเวลาArrayList.clear()คือO(n)และremoveAllเป็นO(n^2)มี

ดังนั้นใช่ArrayList.clearเร็วกว่ามาก


15

วิธีการเอาองค์ประกอบทั้งหมดของเดี่ยวclear() ArrayListเป็นการดำเนินการที่รวดเร็วเนื่องจากเพิ่งตั้งค่าองค์ประกอบของอาร์เรย์เป็นnullก็ดำเนินการได้อย่างรวดเร็วในขณะที่มันเป็นเพียงแค่กำหนดองค์ประกอบมากมายที่จะ

removeAll(Collection)วิธีการที่จะรับมาจากAbstractCollectionเอาองค์ประกอบทั้งหมดที่อยู่ในคอลเลกชันโต้แย้งจากคอลเลกชันที่คุณเรียกวิธีการใน เป็นการดำเนินการค่อนข้างช้าเนื่องจากต้องค้นหาผ่านคอลเล็กชันที่เกี่ยวข้อง


ฉันคิดว่ามันแค่ตั้งค่าทั้งหมดไม่ใช่องค์ประกอบบางอย่างเป็นโมฆะ หากไม่ใช่กรณีดังกล่าวจะตัดสินได้อย่างไรว่าองค์ประกอบใดควรตั้งค่าเป็นศูนย์
Farid

2
@Farid ขออภัยภาษาอังกฤษของฉันไม่เป็นทางการเกินไป ฉันหมายถึงว่ามันทำให้องค์ประกอบทั้งหมดเป็นโมฆะ ฉันจะซ่อมมัน!
Ernest Friedman-Hill

7

เว้นแต่จะมีการปรับให้เหมาะสมเฉพาะที่จะตรวจสอบว่าข้อโต้แย้งที่ส่งไปยังremoveAll()การรวบรวมตัวเอง (และฉันสงสัยอย่างมากว่าการเพิ่มประสิทธิภาพดังกล่าวจะมี) มันจะช้าลงอย่างมีนัยสำคัญ.clear()ช้ากว่าที่เรียบง่าย

นอกเหนือจากนั้น (และที่สำคัญอย่างน้อยเท่าเทียมกัน): arraylist.removeAll(arraylist)เป็นเพียงป้านสับสนรหัส มันเป็นวิธีที่ย้อนกลับอย่างมากในการพูดว่า "เคลียร์คอลเล็กชันนี้" มันจะมีประโยชน์อะไรต่อคนที่เข้าใจได้มาก arraylist.clear() ?


7

พวกเขาตอบสนองวัตถุประสงค์ที่แตกต่าง clear()เคลียร์อินสแตนซ์ของคลาสremoveAll()ลบอ็อบเจ็กต์ที่กำหนดทั้งหมดและส่งคืนสถานะของการดำเนินการ


คุณช่วยจัดหาทรัพยากรในการอ่านเรื่องข้างต้นเพื่อการอ้างอิงที่ละเอียด
กว่านี้ได้ไหม

1
@KasunSiyambalapitiya วิธีการเกี่ยวกับคำตอบที่ยอมรับซึ่งมีรหัสที่มาสำหรับทั้งสอง?
Abdul

5

clear() จะผ่าน Array ที่แฝงอยู่และตั้งค่าแต่ละรายการเป็น null

removeAll(collection) จะผ่านการตรวจสอบ ArrayList สำหรับการรวบรวมและ remove(Object)หากมีอยู่

ฉันจะจินตนาการว่าclear()เป็นวิธีที่เร็วกว่าแล้วลบทั้งหมดเพราะมันไม่ได้เปรียบเทียบ ฯลฯ


2

Clear เร็วขึ้นเพราะไม่ได้วนลูปมากกว่าองค์ประกอบที่จะลบ วิธีนี้สามารถสันนิษฐานได้ว่าองค์ประกอบทั้งหมดสามารถลบได้

Remove allไม่ได้หมายความว่าจะลบองค์ประกอบทั้งหมดในรายการเฉพาะที่มีให้เป็นพารามิเตอร์ควรลบ ดังนั้นจึงจำเป็นต้องมีความพยายามมากขึ้นในการรักษาสิ่งที่ไม่ควรลบ

ชี้แจง

โดย 'วน' ฉันหมายถึงมันไม่จำเป็นต้องตรวจสอบว่าองค์ประกอบควรจะเก็บไว้หรือไม่ มันสามารถตั้งค่าการอ้างอิงถึงnullโดยไม่ต้องค้นหาผ่านรายการขององค์ประกอบที่ให้ไว้เพื่อลบ

Cleardeleteallจะเร็วกว่า


1
ฉันค่อนข้างแน่ใจว่าArrayList.clear()ต้องวนซ้ำเช่นกัน
โจอาคิมซาวเออร์

@JVerstry คุณหมายถึงว่า clear () ไม่ได้ลบองค์ประกอบที่ลบออกจาก ArrayList หรือไม่
ateiob

1
ไม่ถูกต้อง clear จะวนซ้ำไปที่อาร์เรย์ภายในและตั้งค่าการอ้างอิงทั้งหมดเป็น null เพื่อให้ตัวรวบรวมขยะทำงานได้
devconsole

1
@Joachim, @devconsole: ฉันคิดว่าเขาหมายความว่ามันไม่จำเป็นต้องวนซ้ำ / ซ้ำในรายการที่กำหนดเป็นพารามิเตอร์ target.removeAll(param)จะย้ำไปparamแล้วโทรtarget.contains(...)ซึ่ง iterates targetกว่า

2
-3 ค่อนข้างรุนแรง หาก JVerstry ต้องการเขาสามารถเขียนการใช้งานจาวาของตนเองตั้งแต่เริ่มต้นซึ่งไม่ได้วนซ้ำ clear () สามารถดำเนินการได้อย่างเป็นไปได้ใน O (1) โดยไม่มีลูปในขณะที่ removeAll () ต้องมีอัลกอริทึม O (n) บางชนิดไม่มีวิธีที่จะทำให้สัญญาของ removeAll () API โดยไม่ตรวจสอบองค์ประกอบทั้งหมด
Julius Musseau

1

ชัดเจน () จะมีประสิทธิภาพมากขึ้น มันจะลบแต่ละรายการทุกรายการ การใช้ removeAll (arraylist) จะทำงานได้มากขึ้นเพราะจะตรวจสอบทุกรายการใน arraylist เพื่อดูว่ามีอยู่ในรายการก่อนที่จะลบหรือไม่


-8

Array => เมื่อมีการจัดสรรพื้นที่สำหรับตัวแปร Array ในขณะใช้งานพื้นที่ที่จัดสรรไม่สามารถขยายหรือลบออกได้

ArrayList => นี่ไม่ใช่กรณีใน arraylist ArrayList สามารถขยายและลดขนาดได้ในขณะใช้งาน พื้นที่ที่จัดสรรสามารถย่อเล็กสุดหรือขยายให้ใหญ่สุดในเวลาทำงาน


สิ่งนี้ไม่ตอบคำถามซึ่งเป็นความแตกต่างระหว่าง ArrayList.clear () และ ArrayList.removeAll () ไม่ใช่ความแตกต่างระหว่าง ArrayList.clear
Pierre

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