¿Por qué está protegido el método removeRange () de AbstractList de Java?

98

¿Alguien tiene alguna idea de por qué el método removeRange en AbstractList (y también en ArrayList ) protected? Parece una operación bastante bien definida y útil, pero aún así, para usarla, nos vemos obligados a subclasificar la implementación de List.

¿Existe alguna justificación oculta? Me parece bastante inexplicable.

Joonas Pulakka
fuente

Respuestas:

163

Sí, porque no es así como se elimina un rango del código externo. En su lugar, haz esto:

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

Esto realmente llama removeRangedetrás de escena.


El OP pregunta por qué removeRangeno forma parte de la ListAPI pública. La razón se describe en el artículo 40 de Effective Java 2nd ed, y la cito aquí:

Hay tres técnicas para acortar listas de parámetros demasiado largas. Una es dividir el método en varios métodos, cada uno de los cuales requiere solo un subconjunto de parámetros. Si se hace de forma descuidada, esto puede conducir a demasiados métodos, pero también puede ayudar a reducir el número de métodos al aumentar la ortogonalidad. Por ejemplo, considere la java.util.Listinterfaz. No proporciona métodos para encontrar el primer o el último índice de un elemento en una sublista, los cuales requerirían tres parámetros. En su lugar, proporciona el subListmétodo, que toma dos parámetros y devuelve una vista de una sublista. Este método se puede combinar con los métodos indexOfo lastIndexOf, cada uno de los cuales tiene un solo parámetro, para producir la funcionalidad deseada. Además, elsubList método se puede combinar con cualquier método que opere en unList instancia para realizar cálculos arbitrarios en sublistas. La API resultante tiene una relación potencia / peso muy alta.

Se puede argumentar que removeRangeno tiene tantos parámetros y, por lo tanto, probablemente no sea candidato para este tratamiento, pero dado que hay una forma de invocar a removeRangetravés del subList, no hay razón para saturar la Listinterfaz con un método redundante.


La AbstractList.removeRangedocumentación dice:

Este método es llamado por la clearoperación en esta lista y sus subListas. Anular este método para aprovechar los aspectos internos de la implementación de la lista puede mejorar sustancialmente el rendimiento de la clearoperación en esta lista y sus subListas.

Además, consulte la implementación de OpenJDK de AbstractList.cleary SubList.removeRange.

Chris Jester-Young
fuente
9
Ok, se puede hacer de esa manera, pero ¿por qué ? Parece incómodo. Los elementos individuales se pueden eliminar de la lista directamente, ¿por qué no entonces varios elementos?
Joonas Pulakka
1
@Joonas: El artículo 40 de Effective Java, 2ª ed. Describe la justificación de esto. Pegaré en la sección correspondiente en caso de que no tengas el libro.
Chris Jester-Young
21
+1 (pregunta respondida). Sin embargo, el hecho de que se dé una justificación no significa que tenga sentido. El proceso de acortar las listas de parámetros dificulta la capacidad de los desarrolladores para comprender las operaciones disponibles en una API, lo que va directamente en contra de la razón por la cual las listas se acortaron en primer lugar.
Sam Harwell
3
Tan típico de java. Hagámoslo más complicado y menos efectivo.
Tomáš Zato - Reincorporación a Monica
2
como nota al margen, ¿notó que las removeRangellamadas arraycopyinnecesarias cuando la ArrayListversión se usa en un rango que abarca hasta el final de la lista? hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/e2117e30fb39/src/share/...~~V~~3rd el numMovedes 0, por lo que todo el código arraycopy podría haber sido puesto en una sola if(como se hace en remove); la diferencia es que a) arraycopy es una llamada nativa, que incurre en una sobrecarga, b) arraycopy siempre verifica la corrección de los