Чому захищений метод deleteLan's removeRange () методом AbstractList?


98

Хтось має якусь ідею, чому метод deleteRange в AbstractList (а також в ArrayList ) protected? Це виглядає як досить чітко визначена і корисна операція, але все-таки для її використання ми змушені підкласифікувати виконання List.

Чи є якесь приховане обґрунтування? Мені здається зовсім незрозумілим.

Відповіді:


163

Так, оскільки це не спосіб видалення діапазону із зовнішнього коду. Натомість зробіть це:

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

Це насправді викликає removeRangeкуліси.


ОП запитує, чому removeRangeце не є частиною Listпублічного API. Причина описана у пункті 40 Ефективної Java 2nd ed, і я цитую її тут:

Існує три методи скорочення занадто довгих списків параметрів. Один полягає в тому, щоб розбити метод на кілька методів, кожен з яких вимагає лише підмножини параметрів. Якщо зробити це необережно, це може призвести до занадто багатьох методів, але це також може допомогти зменшити кількість методів шляхом збільшення ортогональності. Наприклад, розглянемо java.util.Listінтерфейс. У ньому не передбачено методів пошуку першого чи останнього індексу елемента в підспілі, для обох яких знадобиться три параметри. Натомість він забезпечує subListметод, який приймає два параметри та повертає перегляд підпису. Цей спосіб може поєднуватися з методами indexOfабо lastIndexOf, кожен з яких має єдиний параметр, щоб отримати бажану функціональність. Більше того,subListметод може бути поєднаний з будь-яким методом, який працює над Listекземпляром для виконання довільних обчислень у списках. Отриманий API має дуже високе співвідношення потужності до ваги.

Можна стверджувати, що removeRangeне має такої кількості параметрів і тому, ймовірно, не є кандидатом на це лікування, але, враховуючи, що існує спосіб викликати removeRangeчерез subList, немає причин захаращувати Listінтерфейс надмірним методом.


AbstractList.removeRange документація говорить:

Цей метод викликається clearоперацією у цьому списку та його підсписками. Перевизначення цього методу, щоб скористатися внутрішніми можливостями реалізації списку, може істотно підвищити ефективність clearоперації в цьому списку та його підсписках.

Також див. Реалізацію AbstractList.clearта SubList.removeRange. OpenJDK .


9
Гаразд, це можна зробити так, але чому ? Здається незручно. Окремі елементи можна вилучити зі списку безпосередньо, чому тоді не кілька елементів?
Joonas Pulakaka

1
@Joonas: Пункт 40 Ефективної Java, 2-е видання описує обґрунтування цього. Я вставлю у відповідний розділ, якщо у вас немає книги.
Кріс Єстер-Янг

21
+1 (відповідь на запитання). Однак те, що це обгрунтування не означає, що це має сенс. Процес скорочення списків параметрів перешкоджає можливості розробників розуміти операції, доступні в API, що працює безпосередньо проти причини, за якою списки скорочуються в першу чергу.
Сем Харвелл

3
Так типово для Java. Давайте зробимо це найскладнішим і найменш ефективним.
Томаш Зато - Відновити Моніку

2
як бічну зауваження, чи помітили ви, що removeRangeдзвінки arraycopyзайві, коли ArrayListверсія використовується в діапазоні, що охоплює до самого кінця списку? hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/e2117e30fb39/src/share/… значення numMoved0 дорівнює, тому весь код масиву копії міг би бути введений в єдиний if(як це зроблено в remove); різниця в тому , що а) ArrayCopy є уродженцем виклик, несучи накладні витрати, б) ArrayCopy чи завжди перевіряти Params на правильність stackoverflow.com/questions/12594046 / ...
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.