Pourquoi la méthode removeRange () de Java AbstractList est-elle protégée?

98

Quelqu'un a-t-il une idée, pourquoi la méthode removeRange dans AbstractList (et aussi dans ArrayList ) est protected? Cela ressemble à une opération assez bien définie et utile, mais pour l'utiliser, nous sommes obligés de sous-classer l'implémentation de List.

Y a-t-il une justification cachée? Cela me semble assez inexplicable.

Joonas Pulakka
la source

Réponses:

163

Oui, car ce n'est pas ainsi que vous supprimez une plage du code extérieur. Au lieu de cela, faites ceci:

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

Cela appelle en fait removeRangeles coulisses.


L'OP demande pourquoi removeRangene fait pas partie de l' ListAPI publique. La raison est décrite dans l'article 40 de Effective Java 2nd ed, et je la cite ici:

Il existe trois techniques pour raccourcir des listes de paramètres trop longues. La première consiste à diviser la méthode en plusieurs méthodes, dont chacune ne nécessite qu'un sous-ensemble de paramètres. Si cela est fait sans précaution, cela peut conduire à trop de méthodes, mais cela peut également aider à réduire le nombre de méthodes en augmentant l'orthogonalité. Par exemple, considérez l' java.util.Listinterface. Il ne fournit pas de méthodes pour rechercher le premier ou le dernier index d'un élément dans une sous-liste, qui nécessiteraient tous deux trois paramètres. Au lieu de cela, il fournit la subListméthode, qui prend deux paramètres et renvoie une vue d'une sous-liste. Cette méthode peut être combinée avec les méthodes indexOfou lastIndexOf, chacune ayant un seul paramètre, pour obtenir la fonctionnalité souhaitée. De plus, lesubListLa méthode peut être combinée avec n'importe quelle méthode qui opère sur une Listinstance pour effectuer des calculs arbitraires sur des sous-listes. L'API qui en résulte a un rapport puissance / poids très élevé.

On peut affirmer que cela removeRangen'a pas beaucoup de paramètres et n'est donc probablement pas un candidat pour ce traitement, mais étant donné qu'il existe un moyen d'invoquer removeRangevia le subList, il n'y a aucune raison d'encombrer l' Listinterface avec une méthode redondante.


La AbstractList.removeRangedocumentation dit:

Cette méthode est appelée par l' clearopération sur cette liste et ses sous-listes. Le remplacement de cette méthode pour tirer parti des éléments internes de l'implémentation de la liste peut considérablement améliorer les performances de l' clearopération sur cette liste et ses sous-listes.

Voir également l'implémentation d'OpenJDK de AbstractList.clearet SubList.removeRange.

Chris Jester-Young
la source
9
Ok, ça peut être fait de cette façon, mais pourquoi ? Cela semble gênant. Des éléments uniques peuvent être supprimés directement de la liste, pourquoi pas plusieurs éléments alors?
Joonas Pulakka
1
@Joonas: le point 40 de Effective Java, 2e éd. En décrit la justification. Je vais coller dans la section appropriée au cas où vous n'auriez pas le livre.
Chris Jester-Young
21
+1 (réponse à la question). Cependant, ce n'est pas parce qu'une justification est donnée que cela a du sens. Le processus de raccourcissement des listes de paramètres empêche les développeurs de comprendre les opérations disponibles dans une API, ce qui va directement à l'encontre de la raison pour laquelle les listes ont été raccourcies en premier lieu.
Sam Harwell
3
Tellement typique de java. Faisons le plus compliqué et le moins efficace.
Tomáš Zato - Réintégrer Monica le
2
en remarque, avez-vous remarqué que des removeRangeappels arraycopyinutilement lorsque la ArrayListversion est utilisée sur une plage allant jusqu'à la toute fin de la liste? hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/e2117e30fb39/src/share/...~~V~~3rd l' numMovedest 0, donc tout le code de arraycopy aurait pu être mis en un seul if(comme cela se fait dans remove); la différence est que a) arraycopy est un appel natif, entraînant une surcharge, b) arraycopy vérifie toujours l' exactitude des paramètres stackoverflow.com/questions/12594046