Pergunta

Esta questão já tem uma resposta aqui:

Ok, então eu estou tyring para percorrer um ArrayList e remover um elemento specefic. No entanto, estou tendo alguns problemas com o cada um para-estrutura como. Quando eu execute o seguinte 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
}

A minha pergunta no, como eu posso fazer 't' um ponteiro para 'arr' para que eu sou capaz de alterar os valores em um loop for-each? Eu sei que eu poderia loop através do ArrayList usando uma estrutura diferente, mas este parece tão limpo e legível, que seria apenas bom ser capaz de fazer 't' um ponteiro.

Todos os comentários são apreciados! Mesmo que você diga que eu deveria apenas chupa-lo e usar uma construção diferente.

Foi útil?

Solução

Eu acho que a melhor abordagem pode ser usar um loop 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");
        }
    }

Outras dicas

O problema é que você está tentando mudar o escopo de loop referência t para deixá-lo apontar para uma nova instância de String. Isso não vai funcionar. Não se refere a entrada real no ArrayList. Você precisa mudar o real valor da referência. Se String era mutável e fornecido um método set() fictício para isso, você poderia, em teoria, fazer

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

ou assim, mas isso não for possível, uma vez que é imutável. Melhor obter uma alça do ponto de entrada na própria matriz usando o loop for normal:

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

Se você insistir em usar o loop for reforçada, então você precisa substituir String por StringBuilder, que é mutável:

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

Lembre-se, Java é passar por valor, não passar por referência.

Para-cada não lhe dá um ponteiro de índice, por isso você não pode usá-lo para alterar um valor imutável.

Ou utilizar uma for-loop com um índice ou usar um tipo mutável (como StringBuf, não String)

Uma matriz de objectos (como cordas) em Java é um bloco contíguo contendo uma série ordenada de referências. Então, quando você tem um conjunto de 4 cordas, o que você realmente tem é de 4 referências armazenados na matriz, e 4 objetos string que estão fora da matriz, mas são referenciados por seus 4 elementos.

O que o para-cada construo em Java faz é criar uma variável local e, para cada iteração, copiar em que a variável local de referência a partir da cula matriz que corresponde a iteração. Quando você definir a variável de loop (t = " some other value") que você está colocando uma referência a uma nova seqüência, "some other value", na variável t local, não na matriz.

Os contrastes com outras linguagens (como Perl) onde a variável do laço age como um alias para o elemento de matriz / lista em si.

Seu código é re-escrito pelo compilador como algo parecido com isto:

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 fazer o que você quer, você teria que escrever o loop como este:

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

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

Iterator não tem o método set, única ListIterator faz.

Basicamente você deseja remover a corda t da lista arr. Basta fazer uma arr.remove (t) e você poderia ser feito. Mas você não pode fazê-lo enquanto a iteração sobre a mesma lista. Você obterá uma exceção se você tentar modificar a lista desta forma.

Você tem duas opções:

  1. clone sua lista, percorrer os clone e remover o 'específica' String da lista original
  2. criar uma lista de candidatos apagar, adicionar todos 'específico' Cordas para essa lista e, depois de iteração através da lista original, percorrer a wastebin e remover tudo o que tiver recolhido aqui da lista original.

A opção 1 é a easist, o clone pode ser feita como:

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

Você parece não entender como os objetos / referências trabalhar em Java, o que é muito fundamental para usar a linguagem de forma eficaz. No entanto, este código aqui deve fazer o que quiser (desculpas para a falta de explicação):

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

Eu acredito, isso não está relacionado com imutável ou mutável.

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

t não mantém a referência ao objeto real. Java copia o valor de ArrayList e coloca esse valor em t de modo valor lista de matriz não se afetam.

HTH

Este tem sido bem atendida. Ainda aqui é a minha sugestão. O loop interno var t é visível apenas lá. Não vai ser visto fora do loop. Você poderia fazer t.set() se não fosse String.

Use um StringBuffer em vez de seqüências de caracteres simples. Desta forma, a cadeia dentro é mutável.

Strings são imutáveis. Se você tivesse um tipo mutável como StringBuilder / buffer, você pode alterar a seqüência em sua iteração. Você tem referências, lembre-se.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top