For-Todos e ponteiros em Java [duplicado]
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.
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:
- clone sua lista, percorrer os clone e remover o 'específica' String da lista original
- 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.