เหตุใดวิธีการ removeRange () ของ AbstractList ของ Java จึงได้รับการป้องกัน


98

ใครมีความคิดบ้างไหมทำไมวิธี removeRange ในAbstractList (และในArrayList ) จึงเป็นprotected ? ดูเหมือนว่าการดำเนินการที่กำหนดไว้ค่อนข้างดีและมีประโยชน์ แต่ถึงกระนั้นหากต้องการใช้เราจะบังคับให้ใช้คลาสย่อยของการใช้งานรายการ

มีเหตุผลบางอย่างซ่อนอยู่หรือไม่? ดูเหมือนจะอธิบายไม่ได้สำหรับฉัน

คำตอบ:


163

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

list.subList(start, end).clear();

นี่เรียกremoveRangeเบื้องหลังจริงๆ


OP ถามว่าเหตุใดจึงremoveRangeไม่เป็นส่วนหนึ่งของListAPI สาธารณะ เหตุผลได้อธิบายไว้ใน Item 40 ของ Effective Java 2nd ed และฉันอ้างถึงที่นี่:

มีสามเทคนิคในการตัดทอนรายการพารามิเตอร์ที่ยาวเกินไป วิธีหนึ่งคือการแยกวิธีการออกเป็นหลายวิธีซึ่งแต่ละวิธีต้องการเพียงส่วนย่อยของพารามิเตอร์ หากทำอย่างไม่ระมัดระวังสิ่งนี้อาจนำไปสู่วิธีการต่างๆมากเกินไป แต่ก็สามารถช่วยลดจำนวนวิธีได้โดยการเพิ่มมุมฉาก ตัวอย่างเช่นพิจารณาjava.util.Listอินเทอร์เฟซ ไม่มีวิธีการในการค้นหาดัชนีแรกหรือตัวสุดท้ายขององค์ประกอบในรายการย่อยซึ่งทั้งสองอย่างจะต้องใช้พารามิเตอร์สามตัว แต่จะให้subListวิธีการซึ่งรับสองพารามิเตอร์และส่งกลับมุมมองของรายการย่อย วิธีนี้สามารถใช้ร่วมกับindexOfหรือlastIndexOfวิธีการซึ่งแต่ละพารามิเตอร์มีพารามิเตอร์เดียวเพื่อให้ได้ฟังก์ชันที่ต้องการ ยิ่งไปกว่านั้นsubListวิธีการสามารถใช้ร่วมกับวิธีการใด ๆที่ดำเนินการบนListอินสแตนซ์เพื่อทำการคำนวณตามอำเภอใจในรายการย่อย API ที่ได้มีอัตราส่วนกำลังต่อน้ำหนักสูงมาก

เราสามารถโต้แย้งได้ว่าremoveRangeไม่มีพารามิเตอร์จำนวนมากดังนั้นจึงอาจไม่ใช่ตัวเลือกสำหรับการรักษานี้ แต่เนื่องจากมีวิธีเรียกใช้removeRangeผ่านทางsubListจึงไม่มีเหตุผลที่จะทำให้Listอินเทอร์เฟซยุ่งเหยิงด้วยวิธีการซ้ำซ้อน


AbstractList.removeRangeเอกสารพูดว่า:

วิธีนี้เรียกโดยการclearดำเนินการในรายการนี้และรายการย่อย เอาชนะวิธีการนี้จะใช้ประโยชน์จาก internals ของการดำเนินรายการที่สามารถอย่างมีนัยสำคัญในการปรับปรุงประสิทธิภาพของclearการดำเนินงานในรายการนี้และรายการย่อยของ

นอกจากนี้โปรดดูการนำ OpenJDK ไปใช้AbstractList.clearและSubList.removeRange.


9
โอเคมันทำได้ แต่ทำไมล่ะ? ดูเหมือนอึดอัด องค์ประกอบเดี่ยวสามารถลบออกจากรายการได้โดยตรงทำไมไม่องค์ประกอบหลายรายการล่ะ
Joonas Pulakka

1
@Joonas: Item 40 ของ Effective Java, 2nd ed อธิบายเหตุผลสำหรับสิ่งนี้ ฉันจะวางในส่วนที่เกี่ยวข้องในกรณีที่คุณไม่มีหนังสือ
Chris Jester-Young

21
+1 (ตอบคำถาม) อย่างไรก็ตามเพียงเพราะการให้เหตุผลไม่ได้หมายความว่ามันสมเหตุสมผล ขั้นตอนการย่อรายการพารามิเตอร์เป็นอุปสรรคต่อความสามารถของนักพัฒนาในการทำความเข้าใจการทำงานที่มีอยู่ใน API ซึ่งตรงกับสาเหตุที่ทำให้รายการสั้นลงตั้งแต่แรก
Sam Harwell

3
เป็นเรื่องปกติสำหรับ java มาทำให้ซับซ้อนที่สุดและมีประสิทธิภาพน้อยที่สุด
Tomáš Zato - คืนสถานะ Monica

2
ในฐานะที่เป็นบันทึกด้านข้างคุณสังเกตเห็นว่าการremoveRangeโทรarraycopyโดยไม่จำเป็นเมื่อใช้ArrayListเวอร์ชันในช่วงที่ครอบคลุมจนถึงตอนท้ายของรายการหรือไม่ hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/e2117e30fb39/src/share/…ค่าnumMovedเป็น 0 ดังนั้นโค้ด arraycopy ทั้งหมดจึงสามารถใส่ลงใน single if(ตามที่ทำในremove); ความแตกต่างคือ a) arraycopy เป็นการเรียกแบบเนทีฟซึ่งมีค่าใช้จ่ายสูง b) arraycopy จะตรวจสอบ params เพื่อความถูกต้อง เสมอstackoverflow.com/questions/12594046/…
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.