Reduciendo un ArrayList a un nuevo tamaño

¿Realmente necesito implementarlo yo mismo?

private void shrinkListTo(ArrayList list, int newSize) { for (int i = list.size() - 1; i >= newSize; --i) list.remove(i); } 

Cree una lista secundaria con el rango de elementos que desea eliminar y luego llame a clear en la lista devuelta.

 list.subList(23, 45).clear() 

Este enfoque se menciona como un idioma en la documentación tanto para List como para ArrayList .


¡Aquí hay un ejemplo de código totalmente probado!

 // limit yourHappyList to ten items int k = yourHappyList.size(); if ( k > 10 ) yourHappyList.subList(10, k).clear(); // sic k, not k-1 

alternativamente puedes usar el método de sublista :

 public static  List shrinkTo(List list, int newSize) { return list.subList(0, newSize - 1); } 

use el método ArrayList # removeRange () :

void protegido removeRange (int fromIndex, int toIndex)

Elimina de esta lista todos los elementos cuyo índice se encuentra entre fromIndex, inclusive y toIndex, exclusive. Desplaza los elementos sucesivos hacia la izquierda (reduce su índice). Esta llamada acorta la lista por (toIndex – fromIndex) elementos. (Si toIndex == fromIndex, esta operación no tiene efecto).

luego use el método ArrayList # trimToSize () :

Recorta la capacidad de esta instancia de ArrayList para que tenga el tamaño actual de la lista. Una aplicación puede usar esta operación para minimizar el almacenamiento de una instancia de ArrayList.

Mi solución :

 public static void shrinkTo(List list, int newSize) { int size = list.size(); if (newSize >= size) return; for (int i = newSize; i < size; i++) { list.remove(list.size() - 1); } } 

Solo usa :

 shrinkTo(yourList, 6); 

Hay otra consideración. Es posible que desee evitar usar una ArrayList en la firma de su método y, en cambio, trabajar con la interfaz de la List , ya que lo vincula con la implementación de ArrayList , lo que dificulta los cambios en la línea si encuentra que, por ejemplo, una LinkedList es más adecuado a sus necesidades. Prevenir este acoplamiento apretado tiene un costo.

Un enfoque alternativo podría tener este aspecto:

 private void shrinkListTo(List list, int newSize) { list.retainAll(list.subList(0, newSize); } 

Desafortunadamente, el método List.retainAll() es opcional para que se implementen las subclases, por lo que deberá catch una UnsupportedOperationException, y luego hacer otra cosa.

 private void shrinkListTo(List list, int newSize) { try { list.retainAll(list.subList(0, newSize); } catch (UnspportedOperationException e) { //perhaps log that your using your catch block's version. for (int i = list.size() - 1; i >= newSize; --i) list.remove(i); } } } 

Eso no es tan sencillo como su original. Si no está vinculado a la instancia de la Lista que está pasando, podría devolver una nueva instancia con la misma subList(int start, int end) llamando a subList(int start, int end) , y ni siquiera tendría que crear un método. Esto también sería una implementación más rápida, ya que (en Java 6), obtendría una instancia de un AbstractList.SubList que contiene su lista, un desplazamiento en ella y un tamaño. No habría necesidad de iterar.

Si está interesado en los argumentos para codificar interfaces en lugar de clases, vea este artículo favorito de Allen Holub