Durchlaufen einer Sammlung, Vermeiden von ConcurrentModificationException beim Entfernen von Objekten in einer Schleife

1194

Wir alle wissen, dass Sie Folgendes nicht tun können, weil ConcurrentModificationException:

for (Object i : l) {
    if (condition(i)) {
        l.remove(i);
    }
}

Aber das funktioniert anscheinend manchmal, aber nicht immer. Hier ist ein spezifischer Code:

public static void main(String[] args) {
    Collection<Integer> l = new ArrayList<>();

    for (int i = 0; i < 10; ++i) {
        l.add(4);
        l.add(5);
        l.add(6);
    }

    for (int i : l) {
        if (i == 5) {
            l.remove(i);
        }
    }

    System.out.println(l);
}

Dies führt natürlich zu:

Exception in thread "main" java.util.ConcurrentModificationException

Auch wenn mehrere Threads dies nicht tun. Wie auch immer.

Was ist die beste Lösung für dieses Problem? Wie kann ich ein Element in einer Schleife aus der Sammlung entfernen, ohne diese Ausnahme auszulösen?

Ich benutze Collectionhier auch eine beliebige , nicht unbedingt eine ArrayList, also kann man sich nicht darauf verlassen get.

Claudiu
quelle
Hinweis für Leser: Lesen Sie docs.oracle.com/javase/tutorial/collections/interfaces/…. Dies ist möglicherweise einfacher, um das zu erreichen, was Sie tun möchten.
GKFX

Antworten:

1601

Iterator.remove() ist sicher, Sie können es so verwenden:

List<String> list = new ArrayList<>();

// This is a clever way to create the iterator and call iterator.hasNext() like
// you would do in a while-loop. It would be the same as doing:
//     Iterator<String> iterator = list.iterator();
//     while (iterator.hasNext()) {
for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
    String string = iterator.next();
    if (string.isEmpty()) {
        // Remove the current element from the iterator and the list.
        iterator.remove();
    }
}

Beachten Sie, dass dies Iterator.remove()der einzig sichere Weg ist, eine Sammlung während der Iteration zu ändern. Das Verhalten ist nicht angegeben, wenn die zugrunde liegende Sammlung während der Iteration auf andere Weise geändert wird.

Quelle: docs.oracle> Die Sammlungsschnittstelle


Wenn Sie ein Element haben ListIteratorund Elemente hinzufügen möchten, können Sie es ListIterator#addaus demselben Grund verwenden , aus dem Sie es verwenden können Iterator#remove - es ist so konzipiert, dass es dies zulässt.


In Ihrem Fall haben Sie versucht aus einer Liste zu entfernen, aber die gleiche Einschränkung gilt für , wenn versucht , puteine in Mapwährend sein Inhalt iterieren.

Bill K.
quelle
19
Was ist, wenn Sie ein anderes Element als das in der aktuellen Iteration zurückgegebene Element entfernen möchten?
Eugen
2
Sie müssen die .remove im Iterator verwenden und das kann nur das aktuelle Element entfernen, also nein :)
Bill K
1
Beachten Sie, dass dies langsamer ist als die Verwendung von ConcurrentLinkedDeque oder CopyOnWriteArrayList (zumindest in meinem Fall)
Dan
1
Ist es nicht möglich, den iterator.next()Aufruf in die for-Schleife zu setzen? Wenn nicht, kann jemand erklären, warum?
Blake
1
@GonenI Es ist für alle Iteratoren aus Sammlungen implementiert, die nicht unveränderlich sind. List.addist in diesem Sinne auch "optional", aber Sie würden nicht sagen, dass es "unsicher" ist, einer Liste hinzuzufügen.
Radiodef
345

Das funktioniert:

Iterator<Integer> iter = l.iterator();
while (iter.hasNext()) {
    if (iter.next() == 5) {
        iter.remove();
    }
}

Ich nahm an, dass die Verwendung eines Iterators nicht helfen würde, da eine foreach-Schleife syntaktischer Zucker für die Iteration ist ... aber sie bietet Ihnen diese .remove()Funktionalität.

Claudiu
quelle
43
foreach loop ist syntaktischer Zucker zum Iterieren. Wie Sie bereits betont haben, müssen Sie auf dem Iterator remove aufrufen, auf das foreach Ihnen keinen Zugriff gewährt. Dies ist der Grund , warum Sie nicht in einer foreach - Schleife entfernen können (auch wenn Sie sind tatsächlich einen Iterator unter der Haube verwendet wird )
madlep
36
+1 zum Beispiel Code zur Verwendung von iter.remove () im Kontext, den die Antwort von Bill K nicht [direkt] hat.
Eddified
202

Mit Java 8 können Sie die neue removeIfMethode verwenden . Auf Ihr Beispiel angewendet:

Collection<Integer> coll = new ArrayList<>();
//populate

coll.removeIf(i -> i == 5);
Assylien
quelle
3
Ooooo! Ich hatte gehofft, dass etwas in Java 8 oder 9 helfen könnte. Das scheint mir immer noch ziemlich ausführlich zu sein, aber ich mag es immer noch.
James T Snell
Wird die Implementierung von equals () auch in diesem Fall empfohlen?
Anmol Gupta
übrigens removeIfverwendet Iteratorund whileSchleife. Sie können es bei Java 8java.util.Collection.java
Omerhakanbilici
3
@omerhakanbilici Einige Implementierungen ArrayListüberschreiben es aus Leistungsgründen. Diejenige, auf die Sie sich beziehen, ist nur die Standardimplementierung.
Didier L
@AnmolGupta: Nein, equalswird hier überhaupt nicht verwendet, muss also nicht implementiert werden. (Aber natürlich, wenn Sie equalsin Ihrem Test verwenden, dann muss es so implementiert werden, wie Sie es wollen.)
Lii
42

Da die Frage bereits beantwortet wurde, dh der beste Weg ist, die Methode remove des Iteratorobjekts zu verwenden, würde ich auf die Besonderheiten des Ortes eingehen, an dem der Fehler "java.util.ConcurrentModificationException"ausgelöst wird.

Jede Kollektion Klasse verfügt über eine eigene Klasse , die den Iterator - Schnittstelle implementiert und stellt Methoden wie next(), remove()und hasNext().

Der Code für next sieht ungefähr so ​​aus ...

public E next() {
    checkForComodification();
    try {
        E next = get(cursor);
        lastRet = cursor++;
        return next;
    } catch(IndexOutOfBoundsException e) {
        checkForComodification();
        throw new NoSuchElementException();
    }
}

Hier ist die Methode checkForComodificationimplementiert als

final void checkForComodification() {
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
}

Wie Sie sehen, versuchen Sie explizit, ein Element aus der Sammlung zu entfernen. Dies führt dazu, modCountdass Sie sich von unterscheiden expectedModCount, was zur Ausnahme führt ConcurrentModificationException.

Ashish
quelle
Sehr interessant. Vielen Dank! Ich rufe oft nicht selbst remove () auf, sondern bevorzuge das Löschen der Sammlung nach dem Durchlaufen. Um nicht zu sagen, das ist ein gutes Muster, genau das, was ich in letzter Zeit gemacht habe.
James T Snell
26

Sie können den Iterator entweder direkt wie erwähnt verwenden oder eine zweite Sammlung behalten und jedes Element, das Sie entfernen möchten, zur neuen Sammlung hinzufügen und am Ende alles entfernen. Auf diese Weise können Sie die Typensicherheit der for-each-Schleife auf Kosten einer erhöhten Speichernutzung und CPU-Zeit weiter nutzen (sollte kein großes Problem sein, es sei denn, Sie haben wirklich, wirklich große Listen oder einen wirklich alten Computer).

public static void main(String[] args)
{
    Collection<Integer> l = new ArrayList<Integer>();
    Collection<Integer> itemsToRemove = new ArrayList<>();
    for (int i=0; i < 10; i++) {
        l.add(Integer.of(4));
        l.add(Integer.of(5));
        l.add(Integer.of(6));
    }
    for (Integer i : l)
    {
        if (i.intValue() == 5) {
            itemsToRemove.add(i);
        }
    }

    l.removeAll(itemsToRemove);
    System.out.println(l);
}
RodeoClown
quelle
7
Dies ist, was ich normalerweise mache, aber der explizite Iterator ist eine elgantere Lösung, die ich fühle.
Claudiu
1
Fair genug, solange Sie mit dem Iterator nichts anderes tun - wenn er verfügbar gemacht wird, ist es einfacher, Dinge wie .next () zweimal pro Schleife usw. aufzurufen. Kein großes Problem, kann aber Probleme verursachen, wenn Sie dies tun Alles, was komplizierter ist, als nur eine Liste durchzugehen, um Einträge zu löschen.
RodeoClown
@RodeoClown: In der ursprünglichen Frage entfernt Claudiu aus der Sammlung, nicht den Iterator.
Matt B
1
Das Entfernen aus dem Iterator wird aus der zugrunde liegenden Sammlung entfernt ... aber was ich im letzten Kommentar gesagt habe, ist, dass, wenn Sie etwas komplizierteres tun, als nur nach Löschungen in der Schleife zu suchen (wie das Verarbeiten korrekter Daten), indem Sie den Iterator verwenden, dies einige bewirken kann Fehler leichter zu machen.
RodeoClown
Wenn es sich um einfache Löschwerte handelt, die nicht benötigt werden, und die Schleife nur das eine tut, ist es absolut in Ordnung, den Iterator direkt zu verwenden und .remove () aufzurufen.
RodeoClown
17

In solchen Fällen ist (war?) Ein häufiger Trick, rückwärts zu gehen:

for(int i = l.size() - 1; i >= 0; i --) {
  if (l.get(i) == 5) {
    l.remove(i);
  }
}

Trotzdem bin ich mehr als froh, dass Sie in Java 8 bessere Möglichkeiten haben, z . B. removeIfoder filterin Streams.

Landei
quelle
2
Das ist ein guter Trick. Bei nicht indizierten Sammlungen wie Sets würde dies jedoch nicht funktionieren, und bei verknüpften Listen wäre dies sehr langsam.
Claudiu
@Claudiu Ja, dies ist definitiv nur für ArrayLists oder ähnliche Sammlungen.
Landei
Ich benutze eine ArrayList, das hat perfekt funktioniert, danke.
StarSweeper
2
Indizes sind großartig. Wenn es so häufig ist, warum benutzt du es nicht for(int i = l.size(); i-->0;) {?
John
16

Gleiche Antwort wie Claudius mit einer for-Schleife:

for (Iterator<Object> it = objects.iterator(); it.hasNext();) {
    Object object = it.next();
    if (test) {
        it.remove();
    }
}
Antzi
quelle
12

Bei Eclipse-Sammlungen funktioniertremoveIf die in MutableCollection definierte Methode :

MutableList<Integer> list = Lists.mutable.of(1, 2, 3, 4, 5);
list.removeIf(Predicates.lessThan(3));
Assert.assertEquals(Lists.mutable.of(3, 4, 5), list);

Mit der Java 8 Lambda-Syntax kann dies wie folgt geschrieben werden:

MutableList<Integer> list = Lists.mutable.of(1, 2, 3, 4, 5);
list.removeIf(Predicates.cast(integer -> integer < 3));
Assert.assertEquals(Lists.mutable.of(3, 4, 5), list);

Der Aufruf von Predicates.cast()ist hier erforderlich, da removeIfder java.util.CollectionSchnittstelle in Java 8 eine Standardmethode hinzugefügt wurde .

Hinweis: Ich bin ein Committer für Eclipse-Sammlungen .

Donald Raab
quelle
10

Erstellen Sie eine Kopie der vorhandenen Liste und durchlaufen Sie die neue Kopie.

for (String str : new ArrayList<String>(listOfStr))     
{
    listOfStr.remove(/* object reference or index */);
}
Priyank Doshi
quelle
19
Das Erstellen einer Kopie klingt nach einer Verschwendung von Ressourcen.
Antzi
3
@Antzi Das hängt von der Größe der Liste und der Dichte der darin enthaltenen Objekte ab. Immer noch eine wertvolle und gültige Lösung.
Mehr
Ich habe diese Methode verwendet. Es braucht etwas mehr Ressourcen, ist aber viel flexibler und klarer.
Tao Zhang
Dies ist eine gute Lösung, wenn Sie nicht beabsichtigen, Objekte innerhalb der Schleife selbst zu entfernen, sondern diese "zufällig" aus anderen Threads entfernt werden (z. B. Aktualisierung von Daten durch Netzwerkvorgänge). Wenn Sie feststellen, dass Sie diese Kopien häufig
ausführen,
8

Die Leute behaupten, man könne nicht aus einer Sammlung entfernen, die von einer foreach-Schleife iteriert wird. Ich wollte nur darauf hinweisen, dass dies technisch nicht korrekt ist, und den Code hinter dieser Annahme genau beschreiben (ich weiß, dass die Frage des OP so weit fortgeschritten ist, dass ich dies nicht weiß):

for (TouchableObj obj : untouchedSet) {  // <--- This is where ConcurrentModificationException strikes
    if (obj.isTouched()) {
        untouchedSet.remove(obj);
        touchedSt.add(obj);
        break;  // this is key to avoiding returning to the foreach
    }
}

Es ist nicht so, dass Sie nicht aus der ColletionIteration entfernen können, sondern dass Sie die Iteration nicht fortsetzen können, wenn Sie dies tun. Daher das breakim obigen Code.

Entschuldigung, wenn diese Antwort ein etwas spezieller Anwendungsfall ist und besser zu dem ursprünglichen Thread passt, von dem ich hierher gekommen bin, ist dieser als Duplikat (obwohl dieser Thread nuancierter erscheint) davon markiert und gesperrt.

John
quelle
8

Mit einer traditionellen for-Schleife

ArrayList<String> myArray = new ArrayList<>();

for (int i = 0; i < myArray.size(); ) {
    String text = myArray.get(i);
    if (someCondition(text))
        myArray.remove(i);
    else
        i++;   
}
Lluis Felisart
quelle
Ah, es ist also wirklich nur die erweiterte for-Schleife, die die Ausnahme auslöst.
Cellepo
FWIW - Derselbe Code funktioniert immer noch, nachdem er geändert wurde, um ihn i++im Schleifenschutz und nicht im Schleifenkörper zu erhöhen .
Cellepo
Korrektur ^: Das heißt, wenn das i++Inkrementieren nicht bedingt wäre - ich sehe jetzt, deshalb machst du es im Körper :)
cellepo
2

Mit A ListIteratorkönnen Sie Elemente zur Liste hinzufügen oder daraus entfernen. Angenommen, Sie haben eine Liste von CarObjekten:

List<Car> cars = ArrayList<>();
// add cars here...

for (ListIterator<Car> carIterator = cars.listIterator();  carIterator.hasNext(); )
{
   if (<some-condition>)
   { 
      carIterator().remove()
   }
   else if (<some-other-condition>)
   { 
      carIterator().add(aNewCar);
   }
}
james.garriss
quelle
Interessant sind die zusätzlichen Methoden in der ListIterator- Schnittstelle (Erweiterung von Iterator) - insbesondere die previousMethode.
Cellepo
1

Ich habe einen Vorschlag für das obige Problem. Keine Notwendigkeit für eine sekundäre Liste oder zusätzliche Zeit. Bitte finden Sie ein Beispiel, das das Gleiche tut, aber auf andere Weise.

//"list" is ArrayList<Object>
//"state" is some boolean variable, which when set to true, Object will be removed from the list
int index = 0;
while(index < list.size()) {
    Object r = list.get(index);
    if( state ) {
        list.remove(index);
        index = 0;
        continue;
    }
    index += 1;
}

Dies würde die Parallelitätsausnahme vermeiden.

Nandhan Thiravia
quelle
1
Die Frage besagt ausdrücklich, dass das OP nicht notwendig ist ArrayListund sich daher nicht darauf verlassen kann get(). Ansonsten aber wahrscheinlich ein guter Ansatz.
Kaskelotti
(Klarstellung ^) OP verwendet eine beliebige Collection- CollectionSchnittstelle enthält nicht get. (Obwohl die FWIW- ListSchnittstelle 'get' enthält).
Cellepo
Ich habe gerade eine separate, detailliertere Antwort hinzugefügt, auch für while-looping a List. Aber +1 für diese Antwort, weil sie zuerst kam.
Cellepo
1

ConcurrentHashMap oder ConcurrentLinkedQueue oder ConcurrentSkipListMap können eine weitere Option sein, da sie niemals eine ConcurrentModificationException auslösen, selbst wenn Sie ein Element entfernen oder hinzufügen.

Ja, ja
quelle
Ja, und beachten Sie, dass diese alle im java.util.concurrentPaket sind. Einige andere ähnliche / häufig verwendete Anwendungsklassen aus diesem Paket sind CopyOnWriteArrayList & CopyOnWriteArraySet [aber nicht auf diese beschränkt].
Cellepo
Eigentlich habe ich gerade gelernt , dass , obwohl derjenigediejenigedasjenige Datenstruktur Objekte zu vermeiden ConcurrentModificationException , so dass sie in einem mit verbessertem -für-Schleife kann noch Ursache Indizierungsprobleme (zB: nach wie vor Elemente überspringen, oder IndexOutOfBoundsException...)
cellepo
1

Ich weiß, dass diese Frage zu alt ist, um sich mit Java 8 zu befassen, aber für diejenigen, die Java 8 verwenden, können Sie removeIf () einfach verwenden:

Collection<Integer> l = new ArrayList<Integer>();

for (int i=0; i < 10; ++i) {
    l.add(new Integer(4));
    l.add(new Integer(5));
    l.add(new Integer(6));
}

l.removeIf(i -> i.intValue() == 5);
pedram bashiri
quelle
1

Eine andere Möglichkeit besteht darin, eine Kopie Ihrer ArrayList zu erstellen:

List<Object> l = ...

List<Object> iterationList = ImmutableList.copyOf(l);

for (Object i : iterationList) {
    if (condition(i)) {
        l.remove(i);
    }
}
Nestor Milyaev
quelle
Hinweis: iist nicht ein indexsondern das Objekt. Vielleicht objwäre es passender , es zu nennen.
Luckydonald
1

Der beste Weg (empfohlen) ist die Verwendung des Pakets java.util.Concurrent. Mit diesem Paket können Sie diese Ausnahme leicht vermeiden. Siehe Geänderter Code

public static void main(String[] args) {
    Collection<Integer> l = new CopyOnWriteArrayList<Integer>();

    for (int i=0; i < 10; ++i) {
        l.add(new Integer(4));
        l.add(new Integer(5));
        l.add(new Integer(6));
    }

    for (Integer i : l) {
        if (i.intValue() == 5) {
            l.remove(i);
        }
    }

    System.out.println(l);
}
jagdish khetre
quelle
0

Falls ArrayList: remove (int index) - if (index ist die Position des letzten Elements) vermeidet es ohne System.arraycopy()und benötigt dafür keine Zeit.

Die Array-Kopierzeit erhöht sich, wenn (der Index nimmt ab), übrigens auch die Elemente der Liste!

Der effektivste Weg zum Entfernen ist das Entfernen seiner Elemente in absteigender Reihenfolge: while(list.size()>0)list.remove(list.size()-1);// nimmt O (1) while(list.size()>0)list.remove(0);// nimmt O (Fakultät (n))

//region prepare data
ArrayList<Integer> ints = new ArrayList<Integer>();
ArrayList<Integer> toRemove = new ArrayList<Integer>();
Random rdm = new Random();
long millis;
for (int i = 0; i < 100000; i++) {
    Integer integer = rdm.nextInt();
    ints.add(integer);
}
ArrayList<Integer> intsForIndex = new ArrayList<Integer>(ints);
ArrayList<Integer> intsDescIndex = new ArrayList<Integer>(ints);
ArrayList<Integer> intsIterator = new ArrayList<Integer>(ints);
//endregion

// region for index
millis = System.currentTimeMillis();
for (int i = 0; i < intsForIndex.size(); i++) 
   if (intsForIndex.get(i) % 2 == 0) intsForIndex.remove(i--);
System.out.println(System.currentTimeMillis() - millis);
// endregion

// region for index desc
millis = System.currentTimeMillis();
for (int i = intsDescIndex.size() - 1; i >= 0; i--) 
   if (intsDescIndex.get(i) % 2 == 0) intsDescIndex.remove(i);
System.out.println(System.currentTimeMillis() - millis);
//endregion

// region iterator
millis = System.currentTimeMillis();
for (Iterator<Integer> iterator = intsIterator.iterator(); iterator.hasNext(); )
    if (iterator.next() % 2 == 0) iterator.remove();
System.out.println(System.currentTimeMillis() - millis);
//endregion
  • für Indexschleife: 1090 ms
  • für absteigenden Index: 519 ms --- das Beste
  • für Iterator: 1043 ms
Nurlan
quelle
0
for (Integer i : l)
{
    if (i.intValue() == 5){
            itemsToRemove.add(i);
            break;
    }
}

Der Haken ist der nach dem Entfernen des Elements aus der Liste, wenn Sie den internen Aufruf von iterator.next () überspringen. es funktioniert noch! Obwohl ich nicht vorschlage, Code wie diesen zu schreiben, hilft es, das Konzept dahinter zu verstehen :-)

Prost!

Srinivasan Thoyyeti
quelle
0

Beispiel für eine Änderung der thread-sicheren Sammlung:

public class Example {
    private final List<String> queue = Collections.synchronizedList(new ArrayList<String>());

    public void removeFromQueue() {
        synchronized (queue) {
            Iterator<String> iterator = queue.iterator();
            String string = iterator.next();
            if (string.isEmpty()) {
                iterator.remove();
            }
        }
    }
}
Yazon2006
quelle
0

Ich weiß, dass diese Frage nur eine Collectionund keine spezifischere voraussetzt List. Aber für diejenigen, die diese Frage lesen und tatsächlich mit einer ListReferenz arbeiten, können Sie sie stattdessen ConcurrentModificationExceptionmit einer whileSchleife vermeiden (während Sie sie ändern), wenn Sie dies vermeiden möchtenIterator (entweder wenn Sie sie generell vermeiden möchten oder wenn Sie sie speziell vermeiden möchten, um sie zu erreichen) eine Schleifenreihenfolge, die sich vom Anhalten von Anfang bis Ende bei jedem Element unterscheidet [was meiner Meinung nach die einzige Reihenfolge ist, die Iteratorselbst ausgeführt werden kann]):

* Update: Siehe Kommentare unten, die verdeutlichen, dass das Analoge auch mit der herkömmlichen -for-Schleife erreichbar ist.

final List<Integer> list = new ArrayList<>();
for(int i = 0; i < 10; ++i){
    list.add(i);
}

int i = 1;
while(i < list.size()){
    if(list.get(i) % 2 == 0){
        list.remove(i++);

    } else {
        i += 2;
    }
}

Keine ConcurrentModificationException von diesem Code.

Dort sehen wir, dass die Schleife nicht am Anfang beginnt und nicht bei jedem Element aufhört (was ich glaubeIterator selbst nicht möglich ist).

FWIW wird auch getaufgerufen list, was nicht möglich wäre, wenn die Referenz nur Collection(anstelle des spezifischeren ListTyps von Collection) wäre - ListSchnittstelle enthält get, CollectionSchnittstelle jedoch nicht. Ohne diesen Unterschied listkönnte die Referenz stattdessen eine Collection[und daher wäre diese Antwort technisch gesehen eine direkte Antwort anstelle einer tangentialen Antwort] sein.

FWIWW Der gleiche Code funktioniert auch nach der Änderung so, dass er bei jedem Element am Anfang beginnt (genau wie bei der IteratorReihenfolge):

final List<Integer> list = new ArrayList<>();
for(int i = 0; i < 10; ++i){
    list.add(i);
}

int i = 0;
while(i < list.size()){
    if(list.get(i) % 2 == 0){
        list.remove(i);

    } else {
        ++i;
    }
}
cellepo
quelle
Dies erfordert jedoch immer noch eine sehr sorgfältige Berechnung der zu entfernenden Angaben.
OneCricketeer
Dies ist auch nur eine detailliertere Erklärung dieser Antwort stackoverflow.com/a/43441822/2308683
OneCricketeer
Gut zu wissen - danke! Diese andere Antwort hat mir geholfen zu verstehen, dass es die erweiterte -for-Schleife ist, die ausgelöst wird ConcurrentModificationException, aber nicht die traditionelle -for-Schleife (die in der anderen Antwort verwendet wird) dachte dann, dass es alles for-Schleifen waren, die die Ausnahme auslösen würden).
Cellepo
0

Eine Lösung könnte darin bestehen, die Liste zu drehen und das erste Element zu entfernen, um die ConcurrentModificationException oder IndexOutOfBoundsException zu vermeiden

int n = list.size();
for(int j=0;j<n;j++){
    //you can also put a condition before remove
    list.remove(0);
    Collections.rotate(list, 1);
}
Collections.rotate(list, -1);
Rahul Vala
quelle
0

Versuchen Sie dies (entfernt alle Elemente in der Liste, die gleich sind i):

for (Object i : l) {
    if (condition(i)) {
        l = (l.stream().filter((a) -> a != i)).collect(Collectors.toList());
    }
}
Oleg Tatarchuk
quelle
0

Sie können auch Rekursion verwenden

Rekursion in Java ist ein Prozess, bei dem sich eine Methode kontinuierlich aufruft. Eine Methode in Java, die sich selbst aufruft, wird als rekursive Methode bezeichnet.

Firas Chebbah
quelle
-2

Dies ist möglicherweise nicht der beste Weg, aber für die meisten kleinen Fälle sollte dies akzeptabel sein:

"Erstellen Sie ein zweites leeres Array und fügen Sie nur die hinzu, die Sie behalten möchten."

Ich erinnere mich nicht, woher ich das gelesen habe ... aus Gründen der Gerechtigkeit werde ich dieses Wiki erstellen, in der Hoffnung, dass jemand es findet oder nur um keine Wiederholung zu verdienen, die ich nicht verdiene.

ajax333221
quelle