2009-07-26 16 views
47

¿Realmente necesito implementarlo yo mismo?Reducción de una lista de arreglos a un nuevo tamaño

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

Fwiw la manera más ordenada a escribir que es ", mientras longitud> límite, elimine el último en e "! – Fattie

Respuesta

95

Crear una sublist con la gama de elementos que desea eliminar y luego llamar clear en la lista devuelta.

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

Este enfoque es mencionado como un idioma en la documentación tanto para List y ArrayList.


¡Aquí tenemos 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 
+0

+1 probablemente la implementación más rápida que retiene el puntero al original – akf

+0

Confirmado por la documentación oficial https://docs.oracle.com/javase/6/docs/api/java/util/List.html#subList(int,%20int). "Por ejemplo, el siguiente modismo elimina un rango de elementos de una lista: list.subList (from, to) .clear();" –

4

uso ArrayList#removeRange() método:

protegido removeRange void (int fromIndex, int toIndex)

elimina de esta lista todos los elementos cuyo índice es entre fromIndex, inclusive, y toIndex , exclusivo. Cambia los elementos sucesivos a la izquierda (reduce su índice). Esta llamada acorta la lista por elementos (toIndex - fromIndex). (Si toIndex == fromIndex, esta operación no tiene efecto.)

a continuación, utilizar ArrayList#trimToSize() método:

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

+0

downvotes sin explicación son inútiles – dfa

+6

método protegido ??? – ripper234

+0

si no puede hacer una subclase, pruebe subList (verifique mi segunda respuesta) – dfa

0

Hay otra consideración. Es posible que desee evitar el uso de un ArrayList en la firma de su método y trabajar en la interfaz List, ya que lo vincula con la implementación ArrayList, dificultando los cambios si encuentra que, por ejemplo, un LinkedList es más adecuado a sus necesidades. Evitar este acoplamiento ajustado tiene un costo.

Un enfoque alternativo podría tener este aspecto:

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

Por desgracia, el método List.retainAll() es opcional para las subclases para poner en práctica, por lo que necesitaría un catchUnsupportedOperationException, y luego hacer otra cosa.

private void shrinkListTo(List<Result> 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 directo como su original. Si no está vinculado a la instancia de la Lista que está transfiriendo, puede devolver fácilmente una nueva instancia llamando al subList(int start, int end), e incluso no necesitaría hacer 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 AbstractList.SubList que contiene su lista, un desplazamiento en ella y un tamaño. No habría necesidad de iterar.

Si usted está interesado en los argumentos para la codificación a las interfaces en lugar de clases, consulte this favorite article by Allen Holub

+1

usando .retainAll() va a ser realmente ineficiente. tendrá que tomar O (n^2) porque para cada elemento de la lista, tiene que ir a través de la sublista para verificarlo (no sabe que es una sublista) – newacct

7

Alternativamente, puede utilizar subList método:

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

sí, pero esto no afecta a la lista original. tal vez los elementos que se eliminarán ya no sean necesarios y quiera liberarlos; este método no lograría eso. – newacct

+1

el GC se encargará de ello – dfa

3

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); 
    } 
} 

sólo tiene que utilizar:

shrinkTo(yourList, 6); 
+0

Parece que me funciona. ¡Gracias! –

+0

La complejidad será O (n * k); k = los números deben ser eliminados. En el peor de los casos, iría hasta O (n2). –

Cuestiones relacionadas