2009-11-30 8 views
7

Ok, also tyre ich es, durch eine ArrayList zu iterieren und ein specefic-Element zu entfernen. Allerdings habe ich einige Probleme mit der For-Each-Struktur. Wenn ich den folgenden Code ausführen:For-Each und Pointer in 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 
} 

Meine Frage in, wie kann ich ‚t‘ ein Zeiger auf ‚arr‘, so dass ich in der Lage bin, die Werte in einer für-jede Schleife zu ändern? Ich weiß, dass ich die ArrayList mit einer anderen Struktur durchlaufen könnte, aber diese sieht so sauber und lesbar aus, es wäre einfach nett, einen Zeiger zu machen.

Alle Kommentare werden geschätzt! Selbst wenn du sagst, ich sollte es einfach aufheben und ein anderes Konstrukt verwenden.

+3

Dies ist nicht über foreach-Schleifen, dies ist ein grundlegendes Missverständnis, wie Java funktioniert – skaffman

+2

Obwohl eine ArrayList von einem Array unterstützt wird: ArrayList! = Array. Verwechsle dich nicht durch das Mischen der Begriffe (wie in deinen Kommentaren) –

+1

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

Antwort

16

Ich denke, der beste Ansatz für eine Schleife verwenden kann.

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

Funktioniert es? Nein ConcurrentModificationException auf diese Weise? –

+2

Ich denke, dass Sie nur diese Ausnahme bekommen, wenn Sie Elemente hinzufügen oder entfernen, während Sie –

+0

iterieren Ja, sicher, Sie verwenden nicht den Iterator mehr, nur eine normale for-Schleife. Nicht aufgepasst;) –

-5

Strings sind unveränderlich. Wenn Sie einen veränderbaren Typ wie StringBuilder/Buffer hatten, könnten Sie die Zeichenfolge in Ihrer Iteration ändern. Sie haben Referenzen, erinnern Sie sich.

+13

Das hat nichts mit 'String' oder 'StringBuilder' oder Unveränderlichkeit, hier geht es darum, wie Objektreferenzen in Java funktionieren. – skaffman

+3

Diese Antwort ist 100% falsch ... – TofuBeer

+0

Der Code wird der lokalen Variable 't' zugewiesen, dies wirkt sich nicht auf die Referenz in der ArrayList aus. Um dies zu ändern, müssen Sie arr.set() wie in der Antwort von MB unten beschrieben aufrufen. – SimonJ

1

For-each gibt Ihnen keinen Indexzeiger, Sie können ihn also einfach nicht verwenden, um einen unveränderlichen Wert zu ändern.

verwenden entweder eine for-Schleife mit einem Index oder eine veränderliche Art verwenden (wie String, nicht String)

0

Grundsätzlich möchten Sie die Zeichenfolge t aus der Liste Arr entfernen. Mach einfach einen arr.remove (t) und du könntest fertig sein. Aber Sie können es nicht während der Iteration über die gleiche Liste tun. Sie erhalten eine Ausnahme, wenn Sie versuchen, die Liste auf diese Weise zu ändern.

Sie haben zwei Möglichkeiten:

  1. Klon Ihrer Liste, durch den Klon iterieren und die ‚spezifischen‘ String aus der ursprünglichen Liste
  2. erstellen eine Liste zum Löschen Kandidaten entfernen, fügen Sie alle ‚spezifischen‘ Strings zu dieser Liste und iteriere durch die ursprüngliche Liste, durch die Mülltonne und entferne alles, was du hier gesammelt hast, aus der ursprünglichen Liste.

Option 1 ist die easist kann der Klon wie gemacht werden:

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

Ein Array von Objekten (wie Strings) in Java ist ein zusammenhängender Block eine geordnete Reihe von Referenzen enthält. Wenn Sie also ein Array mit 4 Strings haben, haben Sie tatsächlich 4 Referenzen im Array gespeichert und 4 String-Objekte, die außerhalb des Arrays liegen, aber durch ihre 4 Elemente referenziert werden. Das For-each-Konstrukt in Java erstellt eine lokale Variable und kopiert für jede Iteration den Verweis aus der Array-Zelle, die dieser Iteration entspricht, in diese lokale Variable. Wenn Sie die Schleifenvariable (t = " some other value") setzen, setzen Sie eine Referenz auf eine neue Zeichenfolge, "some other value", in die lokale Variable t, nicht in das Array.

Der Kontrast zu einigen anderen Sprachen (wie Perl), bei denen die Schleifenvariable wie ein Alias ​​für das Array-/Listenelement selbst wirkt.

+0

+1 für eine erstaunliche Erklärung! – Hassan

0

Sie scheinen zu verstehen, wie Objekte/Referenzen in Java funktionieren, was ziemlich grundlegend für die effektive Verwendung der Sprache ist.Allerdings sollte dieser Code hier tun, was Sie (Entschuldigung für die fehlende Erklärung) wollen:

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

Das Problem ist, dass Sie versuchen, die Loop-scoped Referenzt zu lassen, um einen Punkt zu ändern neue String-Instanz Das wird nicht funktionieren. Es bezieht sich nicht auf den tatsächlichen Eintrag in der Arraylist. Sie müssen den tatsächlichen Wert der Referenz ändern. Wenn String wandelbar war und lieferte eine fiktive set() Methode für das, könnte man theoretisch tun

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

oder so, aber das ist nicht möglich, da es unveränderlich ist. Besser erhalten einen Griff des Einstiegspunktes in der Anordnung selbst die normale for Schleife:

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

Wenn Sie bei der Verwendung der erweiterten for Schleife bestehen, dann müssen Sie String durch StringBuilder ersetzen, die wandelbar ist:

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

Denken Sie daran, Java ist Pass-by-Wert, nicht Pass-by-Referenz.

+0

Noch schlimmer - sein erster Satz sagt uns, dass er etwas entfernen will (macht Sinn, scheint die eigentliche Zuordnung für die example.buab-user-group zu sein;)) aber sein Code zeigt einen Ersatz ... das wird sei eine laaaaaange nacht :) –

+0

Wtf, er wollte ** es ** entfernen. Da brauchst du den heiligen Iterator. – BalusC

1

Ihr Code wird vom Compiler als so etwas wie diese neu geschrieben:

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 
} 

zu tun, was Sie wollen, dass die so für Schleife schreiben würde:

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

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

Iterator tut habe nicht die set-Methode, nur ListIterator tut es.

0

Ich glaube, dies ist nicht unveränderlich oder veränderlich.

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

t enthält nicht den Verweis auf das tatsächliche Objekt. Java kopiert den Wert von arraylist und setzt diesen Wert in t, damit der Array-Listenwert nicht beeinflusst wird.

HTH

+0

Das ist eigentlich mehr in der Richtung von dem, was ich ursprünglich dachte. Ich habe mich gefragt, ob ich eine Referenz auf das Objekt bekommen könnte, aber da es unveränderlich ist, denke ich, ist es egal. –

0

Dies wurde gut beantwortet. Hier ist noch mein Vorschlag. Die innere Schleife ist nur dort sichtbar. Es wird nicht außerhalb der Schleife gesehen. Sie könnten t.set() tun, wenn es nicht String wäre.

0

Verwenden Sie eine StringBuffer statt einfache Zeichenfolgen. Auf diese Weise ist die Zeichenfolge innerhalb veränderbar.