Mengapa metode removeRange () AbstractList Java dilindungi?

98

Apakah ada yang tahu, mengapa metode removeRange di AbstractList (dan juga di ArrayList ) protected? Ini terlihat seperti operasi yang cukup terdefinisi dengan baik dan berguna, tetapi tetap saja, untuk menggunakannya, kami dipaksa untuk membuat subclass implementasi List.

Apakah ada alasan tersembunyi? Sepertinya tidak bisa dijelaskan oleh saya.

Joonas Pulakka
sumber

Jawaban:

163

Ya, karena bukan itu cara Anda menghapus rentang dari kode luar. Sebaliknya, lakukan ini:

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

Ini sebenarnya panggilan di removeRangebelakang layar.


OP bertanya mengapa removeRangebukan bagian dari ListAPI publik. Alasannya dijelaskan pada Item 40 Effective Java 2nd ed, dan saya kutip di sini:

Ada tiga teknik untuk mempersingkat daftar parameter yang terlalu panjang. Salah satunya adalah memecah metode menjadi beberapa metode, yang masing-masing hanya memerlukan sebagian dari parameter. Jika dilakukan secara sembarangan, ini dapat menyebabkan terlalu banyak metode, tetapi juga dapat membantu mengurangi jumlah metode dengan meningkatkan ortogonalitas. Misalnya, perhatikan java.util.Listantarmuka. Ini tidak menyediakan metode untuk menemukan indeks pertama atau terakhir dari sebuah elemen dalam sublist, yang keduanya membutuhkan tiga parameter. Sebagai gantinya, ia menyediakan subListmetode, yang mengambil dua parameter dan mengembalikan tampilan sublist. Metode ini dapat dikombinasikan dengan metode indexOfatau lastIndexOf, yang masing-masing memiliki parameter tunggal, untuk menghasilkan fungsionalitas yang diinginkan. ApalagisubListmetode dapat digabungkan dengan metode apa pun yang beroperasi pada sebuah Listinstance untuk melakukan penghitungan sewenang-wenang pada sublist. API yang dihasilkan memiliki rasio power-to-weight yang sangat tinggi.

Seseorang dapat berargumen bahwa removeRangetidak memiliki banyak parameter dan oleh karena itu mungkin bukan kandidat untuk perlakuan ini, tetapi mengingat bahwa ada cara untuk memanggil removeRangemelalui subList, tidak ada alasan untuk mengacaukan Listantarmuka dengan metode yang berlebihan.


The AbstractList.removeRangedokumentasi mengatakan:

Metode ini dipanggil oleh clearoperasi pada daftar ini dan sublistnya. Mengganti metode ini untuk memanfaatkan internal implementasi daftar dapat secara substansial meningkatkan kinerja clearoperasi pada daftar ini dan subListnya.

Juga, lihat implementasi OpenJDK dari AbstractList.cleardan SubList.removeRange.

Chris Jester-Young
sumber
9
Ok, memang bisa seperti itu, tapi kenapa ? Sepertinya canggung. Elemen tunggal dapat dihapus dari daftar secara langsung, mengapa tidak banyak elemen?
Joonas Pulakka
1
@Joonas: Item 40 of Effective Java, 2nd ed menjelaskan alasan untuk ini. Saya akan menempel di bagian yang relevan jika Anda tidak memiliki bukunya.
Chris Jester-Young
21
+1 (pertanyaan dijawab). Namun, hanya karena alasan diberikan tidak berarti itu masuk akal. Proses memperpendek daftar parameter menghalangi kemampuan pengembang untuk memahami operasi yang tersedia di API, yang bekerja secara langsung melawan alasan mengapa daftar dipersingkat sejak awal.
Sam Harwell
3
Sangat khas untuk java. Mari membuatnya paling rumit dan paling tidak efektif.
Tomáš Zato - Kembalikan Monica
2
sebagai catatan tambahan, apakah Anda memperhatikan bahwa removeRangepanggilan arraycopytidak perlu saat ArrayListversi digunakan pada rentang yang mencakup hingga akhir daftar? hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/e2117e30fb39/src/share/... yang numMovedadalah 0, sehingga seluruh kode arraycopy bisa saja dimasukkan ke dalam satu if(seperti yang dilakukan di remove); perbedaannya adalah bahwa a) arraycopy adalah panggilan asli, menimbulkan overhead, b) arraycopy selalu memeriksa parameter untuk kebenaran stackoverflow.com/questions/12594046/…