674 Stimmen

Aufruf von remove in der foreach-Schleife in Java

Ist es in Java legal, remove für eine Sammlung aufzurufen, wenn man die Sammlung mit einer foreach-Schleife durchläuft? Zum Beispiel:

List<String> names = ....
for (String name : names) {
   // Do something
   names.remove(name).
}

Ist es außerdem legal, Elemente zu entfernen, die noch nicht überarbeitet wurden? Zum Beispiel,

//Assume that the names list as duplicate entries
List<String> names = ....
for (String name : names) {
    // Do something
    while (names.remove(name));
}

34 Stimmen

Kein guter Plan. Nur weil die Sprache es bei einem bestimmten Lauf toleriert, ist es noch lange keine gute Idee.

0 Stimmen

Sie müssen mich in einer schlechten Stimmung erwischt haben, aber mir scheint, die Antwort auf diese Frage kommt direkt aus der foreach-Dokumentation.

2 Stimmen

30voto

Ja, Sie können die for-each-Schleife verwenden, Dazu müssen Sie eine separate Liste führen, die die zu entfernenden Elemente enthält, und diese Liste dann aus der Namensliste entfernen, indem Sie removeAll() Methode,

List<String> names = ....

// introduce a separate list to hold removing items
List<String> toRemove= new ArrayList<String>();

for (String name : names) {
   // Do something: perform conditional checks
   toRemove.add(name);
}    
names.removeAll(toRemove);

// now names list holds expected values

5voto

bmcdonald Punkte 301

Vergewissern Sie sich, dass es sich nicht um Codegeruch handelt. Ist es möglich, die Logik umzukehren und "inklusiv" statt "exklusiv" zu sein?

List<String> names = ....
List<String> reducedNames = ....
for (String name : names) {
   // Do something
   if (conditionToIncludeMet)
       reducedNames.add(name);
}
return reducedNames;

Die Situation, die mich zu dieser Seite geführt hat, betraf einen alten Code, der eine Liste in einer Schleife durchlief und Unbestimmtheiten verwendete, um Elemente aus der Liste zu entfernen. Ich wollte den Code so umgestalten, dass er den foreach-Stil verwendet.

Es durchlief eine ganze Liste von Elementen, um zu überprüfen, auf welche der Benutzer Zugriffsrechte hatte, und entfernte diejenigen aus der Liste, für die er keine Rechte hatte.

List<Service> services = ...
for (int i=0; i<services.size(); i++) {
    if (!isServicePermitted(user, services.get(i)))
         services.remove(i);
}

Um dies rückgängig zu machen und das Entfernen nicht zu verwenden:

List<Service> services = ...
List<Service> permittedServices = ...
for (Service service:services) {
    if (isServicePermitted(user, service))
         permittedServices.add(service);
}
return permittedServices;

Wann wäre "entfernen" vorzuziehen? Eine Überlegung ist, wenn gien eine große Liste oder teure "add", kombiniert mit nur ein paar entfernt im Vergleich zu der Liste Größe. Es könnte effizienter sein, nur einige wenige Löschungen vorzunehmen als viele Hinzufügungen. Aber in meinem Fall war eine solche Optimierung nicht angebracht.

4voto

sanity Punkte 34573

Diejenigen, die sagen, dass Sie nicht sicher ein Element aus einer Sammlung außer durch den Iterator entfernen können, sind nicht ganz richtig, Sie können es sicher mit einer der gleichzeitigen Sammlungen wie ConcurrentHashMap tun.

1voto

Carsten Punkte 19
  1. Versuchen Sie dies 2. und ändern Sie die Bedingung in "WINTER" und Sie werden sich wundern:

    public static void main(String[] args) { Season.add("Frühling"); Season.add("Sommer"); Season.add("Herbst"); Season.add("WINTER"); for (String s : Season) { if(!s.equals("Sommer")) { System.out.println(s); continue; } Season.remove("Frühling"); } }

1voto

song Punkte 19

Es ist besser, einen Iterator zu verwenden, wenn Sie ein Element aus einer Liste entfernen möchten

denn der Quellcode von remove ist

if (numMoved > 0)
    System.arraycopy(elementData, index+1, elementData, index,
             numMoved);
elementData[--size] = null;

Wenn Sie also ein Element aus der Liste entfernen, wird die Liste umstrukturiert, der Index des anderen Elements wird geändert, dies kann dazu führen, dass etwas passiert, was Sie wollen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X