2010-06-23 11 views
13

Soy nuevo en programación Java, estado programando en php así que estoy acostumbrado a este tipo de bucle:Cómo quitar todo, desde un ArrayList en Java, pero el primer elemento

int size = mapOverlays.size(); 
for(int n=1;n<size;n++) 
{ 
    mapOverlays.remove(n); 
} 

Así que desea eliminar todo menos el primer elemento, entonces, ¿por qué no funciona? Como lo entiendo, después de la eliminación, las teclas de matriz se reorganizan o no?

+0

Por lo que yo puedo entender, usted está recogiendo el tamaño de una lista llamada itemizedOverlay, y trabajar en otra lista llamada mapOverlays. Espero que eso sea normal ;-) – Agemen

+0

Lo siento, un error tipográfico, las matrices son las mismas, he editado – dfilkovi

Respuesta

19

Según lo entiendo, después de la eliminación, las teclas de matriz se reorganizan o no? Sí, el elemento que estaba en la posición 2 está en la posición 1 después de quitar el elemento en la posición 1.

Usted puede intentar esto:

Object obj = mapOverlays.get(0); // remember first item 
mapOverlays.clear(); // clear complete list 
mapOverlays.add(obj); // add first item 
+4

Esto puede funcionar pero hace que la lista entre en un estado intermedio innecesario. Si la lista se usa al mismo tiempo (quizás sea una CopyOnWriteArrayList), debe evitar esta solución. –

6

¿Por qué no intenta al revés?

int size = itemizedOverlay.size(); 
for(int n=size-1;n>0;n--) 
{ 
    mapOverlays.remove(n); 
} 
+2

-1 En algunas implementaciones de listas esto funcionará * terriblemente *, y nunca estará cerca de lo óptimo. –

+0

@Kevin, el OP no está utilizando "alguna Lista". Dijo en términos muy claros que es una "ArrayList".Hasta donde sé, este será 'O (n)' para todas las listas integradas en Java. Esto incluye 'LinkedList'. –

+0

innecesariamente complicado. Las respuestas anteriores leen mejor. – cyclical

2

Un ArrayList tiene índices enteros de 0 a size() - 1. Usted podría hacer:

int size = mapOverlays.size(); 
for(int n=1;n<size;n++) 
{ 
    mapOverlays.remove(1); 
} 

Esto probablemente coincida con lo que usted espera de PHP. Funciona al eliminar continuamente el 1er elemento, que cambia. Sin embargo, esto tiene un rendimiento pobre, ya que la matriz interna debe cambiar constantemente hacia abajo. Es mejor usar clear() o ir en orden inverso.

Es una lástima removeRange está protegido, ya que sería conveniente para este tipo de operación.

+0

+1 para señalar la desventaja de rendimiento de su solución potencial. Además ... recuerda que siempre puedes extender ArrayList y hacer público cualquier método que esté protegido. –

+0

No necesita 'removeRange' (y el problema no es que esté protegido, sino que ni siquiera existe en la interfaz' List' (y con razón)). Vea la respuesta de Adam Crune. –

+0

@Kevin, el OP no está utilizando la interfaz 'List', por lo que es un non-sequitur. Podría argumentar que debería hacerlo, pero tal vez esté seguro de que explícitamente quiere una clase basada en arreglos para sus características de rendimiento. –

1

Supongo que mapOverlays tiene una referencia ArrayList.

Si mapOverlays está declarada como una List o ArrayList, a continuación, mapOverlays.remove(n) se referirá al método remove(int) que elimina el objeto en un offset dado. (Hasta aquí todo bien ...)

Cuando se quita el elemento nth de una matriz mediante remove(int), los elementos empezando en la posición n + 1 y sobre todo son movidos hacia abajo por uno. Entonces, lo que estás haciendo en realidad no funcionará en la mayoría de los casos. (De hecho, es probable que eliminar aproximadamente la mitad de los elementos que desea eliminar y, a continuación, obtener un IndexOutOfBoundsException.)

La mejor solución es o bien:

for (int i = size - 1; i > 0; i--) { 
     mapOverlays.remove(i); 
    } 

o

tmp = mapOverlays.remove(0); 
    mapOverlays.clear(); 
    mapOverlays.add(tmp); 

(Tenga en cuenta que la primera solución siempre se elimina del final de la lista, evitando la necesidad de copiar elementos para completar el agujero dejado por el elemento eliminado. El rendimiento diferente es significativo para una ArrayList grande)

Sin embargo, si mapOverlays se declara como Collection, remove(n) se vinculará a la sobrecarga remove(<E>) que elimina el objeto que coincide con su argumento. Dependiendo del tipo declarado, esto le dará un error de compilación, o el int se autoboxeará como Integer y usted (probablemente) no eliminará nada.GOTCHA!

2

Simple.

mapOverlays = Collections.singletonList(mapOverlays.get(0)); 
+1

Tal vez no sea lo que el OP quiere: la lista resultante no tiene más que el primer elemento, pero ya no puede agregar nada. Por lo tanto, no es una respuesta incorrecta pero presenta algunas limitaciones. –

4

Creo que sería más rápido crear una nueva ArrayList con solo el primer elemento dentro. algo así como:

E temp = mapOverlays.get(0); 
mapOverlays = new ArrayList<E>().add(temp); 
+0

Por cierto, la propuesta de Daniel es tal vez mejor, porque no crea un objeto nuevo. Entonces las referencias al objeto permanecen. – Agemen

0

Si está utilizando una aplicación en lugar de la matriz java.util.List, el tamaño de la matriz se pone cada vez más pequeño que quitar algo y el elemento n+1 reemplaza el elemento n. Este código eventualmente resultará en ArrayIndecOutOfBoundsException cuando n supera el último índice en la lista.

Java también tiene un tipo de matriz y el tamaño de los que uno no se puede cambiar:

Object[] mapOverlay = //initialize the array here 
int size = mapOverlay.length; 
for(int n=1;n<size;n++) 
{ 
    mapOverlay[n] = null; 
} 

No sé PHP, pero esto suena como que está cerca el comportamiento que está después. Sin embargo, las implementaciones de List son más flexibles y cómodas de usar que las matrices.

EDIT: Aquí hay un enlace a la Javadoc de List.remove(int): http://java.sun.com/javase/6/docs/api/java/util/List.html#remove%28int%29

86

Usted podría utilizar

mapOverlays.subList(1, mapOverlays.size()).clear(); 
+7

+1 Es simplemente increíble para mí que esta no sea la respuesta mejor calificada. Es el más simple de codificar * y * probablemente sea el más eficiente (ya que cada implementación de la Lista realizará la tarea de la forma más óptima dada su estructura). –

+1

mierda sagrada, pasó de 2 votos a la mejor calificada en solo una hora! –

+0

Esta es una forma útil de escribirlo. Sin embargo, si realmente miras el código, usa el protegido 'removeRange', y básicamente hace exactamente lo mismo que la solución de Plamena. La principal diferencia es la cantidad de llamadas a métodos y dónde está el bucle. Con un buen JIT, sospecho que tienen un rendimiento bastante similar. Claramente, la gran O es la misma. –

0
int size = mapOverlays.size(); 
for(int n=0;n<size;n++) 
{ 
    mapOverlays.remove(n); 
} 

en Java, si mapOverlays está lista entonces se inicia con 0 como un primer índice. Entonces n = 0 in para bucle.

+0

Creo que OP quiere mantener el primer elemento en la lista y eliminar todo lo demás. –

0

Utilice un bucle while para eliminar todo después de que el primer elemento:

while (mapOverlays.size() > 1) { 
    mapOverlays.remove(1); 
} 

EDITAR (ver comentario de Adam Crume)

Si el rendimiento es un problema que debe utilizar éste

while (mapOverlays.size() > 1) { 
    mapOverlays.remove(mapOverlays.size()-1); 
} 

incluso un poco de micro-optimización

int last = mapOverlays.size() - 1; 
while (last >= 1) { 
    mapOverlays.remove(last); 
    last -= 1; 
} 



si el rendimiento es realmente un problema (y la lista tiene un montón de elementos), se debe utilizar la solución sublist. Es un poco más difícil de leer, pero probablemente sea la solución más rápida si la instancia de la lista no se puede recrear (se hace referencia en otro lugar).

+0

Para una ArrayList, esto funcionará muy mal - O (n^2) tiempo - porque tiene que llamar a System.arraycopy durante casi toda la matriz n-1 veces. Elimine el último elemento en lugar del que está en el índice 1, y debería ser mucho mejor. –

+0

@ Adam - correcto, respuesta editada, y tal vez la solución 'remove (1)' es aún peor que O (n^2) pero yo preferiría que las listas pequeñas fueran más legibles (IMO) - la pregunta no mencionó rendimiento en absoluto. La solución 'sublist' es elegante y mejor (la mejor) pero no todos entienden cómo funciona' sublist'. –

+0

No me importa si las personas no usan la sublista. Simplemente creo que reducir el tiempo de ejecución de O (n^2) a O (n) vale un pequeño sacrificio para la legibilidad. La solución 'remove (1)' puede funcionar bien para listas pequeñas, pero creo que es mejor tener un código que funcione bien para cualquier lista. –

Cuestiones relacionadas