Pregunta

    

Esta pregunta ya tiene una respuesta aquí:

         

Ok, entonces estoy intentando iterar a través de una ArrayList y eliminar un elemento específico. Sin embargo, estoy teniendo algunos problemas para usar la estructura Me gusta para cada uno. Cuando ejecuto el siguiente código:

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 en, ¿cómo puedo hacer 't' un puntero a 'arr' para que pueda cambiar los valores en un ciclo for-each? Sé que podría recorrer ArrayList usando una estructura diferente, pero esta se ve tan limpia y legible que sería bueno poder hacer 't' un puntero.

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

¿Fue útil?

Solución

Creo que el mejor enfoque puede ser usar un bucle for.

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

Otros consejos

El problema es que está tratando de cambiar la referencia t con ámbito de bucle para que apunte a una nueva instancia de String. Esto no va a funcionar. No hace referencia a la entrada real en la lista de arrays. Debe cambiar el valor real de la referencia. Si String era mutable y proporcionaba un método ficticio set () para eso, en teoría podría hacerlo

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

más o menos, pero eso no es posible ya que es inmutable. Es mejor obtener un identificador del punto de entrada en la matriz usando el bucle for normal:

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

Si insiste en utilizar el bucle mejorado for , debe reemplazar String por StringBuilder , que es mutable:

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

Recuerde, Java es paso por valor, no paso por referencia.

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

Use un bucle for con un índice o use un tipo mutable (como StringBuffer, no String)

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

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 configura la variable de bucle ( t = " algún otro valor " ) está poniendo una referencia a una nueva cadena, " algún otro valor " , en el local variable t, no en la matriz.

Los contrastes con algunos otros lenguajes (como Perl) donde la variable de bucle actúa como un alias del elemento matriz / lista en sí.

El compilador reescribe su código de la siguiente manera:

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 quieras, deberías escribir el bucle for de esta manera:

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

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

Iterator no tiene el método set, solo ListIterator sí.

Básicamente desea eliminar la cadena t de la lista arr. Simplemente haz un arr.remove (t) y podrías terminar. Pero no puedes hacerlo mientras iteras sobre la misma lista. Obtendrá una excepción si intenta modificar la lista de esta manera.

Tienes dos opciones:

  1. clone su lista, repita el clon y elimine la cadena 'específica' de la lista original
  2. cree una lista para eliminar candidatos, agregue todas las cadenas 'específicas' a esa lista y, después de recorrer la lista original, iterar a través del basurero y eliminar todo lo que ha recogido aquí de la lista original.

La opción 1 es la fácil, el clon se puede hacer como:

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

Parece que no comprende cómo funcionan los objetos / referencias en Java, lo cual es bastante fundamental para utilizar el lenguaje de manera efectiva. Sin embargo, este código debe hacer lo que desee (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); 
}

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 matrices y lo pone en t para que el valor de la lista de matrices no se vea afectado.

HTH

Esto ha sido respondido bien. Todavía aquí está mi sugerencia. La var t dentro del bucle solo es visible allí. No se verá fuera del bucle. Podría hacer t.set () si no fuera String .

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

Las cadenas son inmutables. Si tuviera un tipo mutable como StringBuilder / Buffer, podría cambiar la cadena en su iteración. Tienes referencias, recuerda.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top