2009-11-30 15 views
7

Ok, entonces estoy tyring para iterar a través de una ArrayList y eliminar un elemento specefic. Sin embargo, estoy teniendo problemas para usar la estructura similar a For-Each. Cuando ejecuto el siguiente código:For-Each y Pointers en Java

ArrayList<String> arr = new ArrayList<String>(); 
//... fill with some values (doesn't really matter) 

for(String t : arr) 
{ 
    t = " some other value "; //hoping this would change the actual array 
} 

for(String t : arr) 
{ 
    System.out.println(t); //however, I still get the same array here 
} 

Mi pregunta, ¿cómo puedo hacer 't' un puntero a 'arr' por lo que yo soy capaz de cambiar los valores en un bucle for-each? Sé que podría recorrer todo el ArrayList usando una estructura diferente, pero esta se ve tan limpia y legible, que sería bueno poder hacer que 't' sea un puntero.

¡Todos los comentarios son apreciados! Incluso si dices que debería chuparlo y usar una construcción diferente.

+3

esto no se trata de foreach loops, este es un malentendido más básico de cómo funciona Java – skaffman

+2

A pesar de que una ArrayList está respaldada por una matriz: ArrayList! = Array. No se confunda al mezclar los términos (como en sus comentarios) –

+1

http://stackoverflow.com/questions/589433/understanding-for-each-loop-in-java –

Respuesta

16

Creo que el mejor enfoque puede ser el uso de un bucle.

ArrayList<String> arr = new ArrayList<String>(); 

    for (int i = 0; i < arr.size(); i++) { 

     String t = arr.get(i); 

     if (// your condition is met) { 
      arr.set(i, "your new value"); 
     } 
    } 
+0

¿Funciona? No ConcurrentModificationException de esta manera? –

+2

Creo que solo obtendrás esa excepción si agregas/quitas elementos de la matriz al iterar –

+0

Sí, claro, ya no estás usando el iterador, solo un ciclo for normal. No prestó atención;) –

-5

Las cadenas son inmutables. Si tiene un tipo mutable como StringBuilder/Buffer, puede cambiar la cadena en su iteración. Usted tiene referencias, recuerde.

+13

Esto no tiene nada que ver con 'String' o 'StringBuilder' o inmutabilidad, se trata de cómo funcionan las referencias de objetos en Java. – skaffman

+3

esta respuesta es 100% incorrecta ... – TofuBeer

+0

El código asigna a la variable local 't', esto no afectará a la referencia dentro de ArrayList. Para cambiar eso, necesita llamar a arr.set() según la respuesta de MB a continuación. – SimonJ

1

Para-cada uno no le da un puntero de índice, por lo que simplemente no puede usarlo para cambiar un valor inmutable.

utilizar un bucle para con un índice o utilizar un tipo mutable (como StringBuffer, no String)

0

Básicamente desea eliminar la Cadena t de la lista arr. Solo haz una arr.remove (t) y podrías haber terminado. Pero no puede hacerlo mientras itera sobre la misma lista. Obtendrá una excepción si intenta modificar la lista de esta manera.

tiene dos opciones:

  1. clon de su lista, iterar por el clon y retire la cadena 'específico' de la lista original
  2. crear una lista de candidatos borrar, añadir todas las cadenas 'específicas' a esa lista y, después de recorrer la lista original, itere a través de la papelera y elimine todo lo que ha recopilado aquí de la lista original.

Opción 1 es la easist, el clon se puede hacer como:

List<String> clone = new ArrayList<String>(arr); 
1

Un conjunto de objetos (como cuerdas) en Java es un bloque contiguo que contiene una serie ordenada de referencias. Por lo tanto, cuando tiene una matriz de 4 cadenas, lo que realmente tiene son 4 referencias almacenadas en la matriz y 4 objetos de cadena que están fuera de la matriz, pero sus 4 elementos hacen referencia a ella.

Lo que hace la construcción for-each en Java es crear una variable local y, para cada iteración, copiar en esa variable local la referencia de la celda de la matriz que corresponde a esa iteración. Cuando establece la variable de bucle (t = " some other value") está poniendo una referencia a una nueva cadena, "some other value", en la variable local t, no en la matriz.

El contraste con algunos otros lenguajes (como Perl) donde la variable de bucle actúa como un alias para el elemento array/list.

+0

+1 para una explicación increíble! – Hassan

0

Parece que no entienden cómo funcionan los objetos/referencias en Java, lo cual es fundamental para usar el lenguaje de forma efectiva.Sin embargo, este código aquí debe hacer lo que quiera (disculpas por la falta de explicación):

ArrayList<String> arr = new ArrayList<String>(); 
//... fill with some values (doesn't really matter) 

for(int i = 0; i < arr.size(); i++) 
{ 
    arr.set(i, " some other value "); // change the contents of the array 
} 

for(String t : arr) 
{ 
    System.out.println(t); 
} 
5

El problema es que usted está tratando de cambiar la referencia de lazo con ámbito de t dejar que apuntan a una nueva instancia de String. Esto no va a funcionar. No refiere la entrada real en el arraylist. Debe cambiar el valor real de la referencia. Si String era mutable y proporciona un método ficticio set() para eso, usted podría, en teoría, hace

for (String t : arr) { 
    t.set("some other value"); 
} 

más o menos, pero eso no es posible, ya que es inmutable. Mejor tener una idea del punto de entrada en la propia matriz mediante la normalidad for bucle:

for (int i = 0; i < arr.size(); i++) { 
    arr.set(i, "some other value"); 
} 

Si usted insiste en el uso de la mayor for bucle, a continuación, es necesario sustituir String por StringBuilder, que es mutable:

for (StringBuilder t : arr) { 
    t.delete(0, t.length()).append("some other value"); 
} 

Recuerde, Java es pasable, no pasa de referencia.

+0

Peor aún: su primera frase nos dice que quiere eliminar algo (tiene sentido, parece ser la asignación real para el ejemplo.buab-user-group;)) pero su código muestra un reemplazo ... esto va a ser una noche loooooong :) –

+0

Wtf, quería ** eliminar **. Ahí necesitas el santo iterador para. – BalusC

1

Su código es re-escrito por el compilador como algo parecido a esto:

ArrayList<String> arr = new ArrayList<String>(); 
//... fill with some values (doesn't really matter) 

for (final Iterator <String> i = arr.iterator(); i.hasNext();) { 
    String t; 

    t = i.next(); 
    t = " some other value "; // just changes where t is pointing 
} 

Para hacer lo que quiera que tendría que escribir el bucle de esta manera:

for (final ListIterator<String> i = arr.iterator(); i.hasNext();) { 
    final String t; 

    t = i.next(); 
    i.set("some other value"); 
} 

iterador hace no tiene el método set, solo lo hace ListIterator.

0

Creo que esto no está relacionado con inmutable o mutable.

t = " some other value "; //hoping this would change the actual array 

t no contiene la referencia al objeto real. Java copia el valor de la lista de arrays y lo coloca en t para que el valor de la lista de arreglos no se vea afectado.

HTH

+0

que en realidad está más en la línea de lo que estaba pensando originalmente. Me preguntaba si podría obtener una referencia al objeto, pero dado que es inmutable, supongo que no importa de todos modos. –

0

Esto ha sido respondido bien. Todavía aquí está mi sugerencia. El lazo dentro de la varilla solo es visible allí. No se verá fuera del circuito. Usted podría hacer t.set() si no fuera String.

0

Use un StringBuffer en lugar de strings simples. De esta forma, la cadena dentro es mutable.