2010-08-26 10 views
12

Ich habe eine ArrayList, die eine Reihe von Elementen enthält, die ich entfernen möchte. Ich habe die IDs der zu entfernenden Elemente in einer anderen Liste gespeichert. Dachte der folgende Code sollte trivialer arbeiten, aber aus irgendeinem Grund, die remove() Anrufe werden einen falschen Wert zurückgibt:Warum funktioniert mein ArrayList.remove (id) -Aufruf nicht?

ArrayList<Integer> toRemove = new ArrayList<Integer>(); 
    ArrayList<JCheckBox> al = new ArrayList<JCheckBox>(); 

    /* Code that adds a bunch of items to al, and a few integers to toRemove */ 

    System.out.println("Size before removing: " + al.size()); 
    for (int i = toRemove.size() - 1; i >= 0; i--) { 
    System.out.println("Removing id: " + toRemove.get(i) + ": "); 
    System.out.println(al.get(toRemove.get(i))); 
    System.out.println(al.remove(toRemove.get(i))); 
    } 
    System.out.println("Size after removing: " + al.size()); 

ich es bekommen würde, wenn die get() Anruf auch einen falschen Wert zurückgegeben, aber es Liefert das Objekt tatsächlich zurück. Was fehlt mir hier?

Der Ausgang des Code oben:

Size before removing: 3 
Removing id: 2: 
javax.swing.JCheckBox[...] 
false 
Size after removing: 3 
+0

Können Sie genaue Deklarationen für 'al' und 'toRemove' posten? –

+0

Hat die gewünschten Definitionen gepostet. – zigdon

Antwort

31

Meine Vermutung ist, dass Sie mit der Tatsache, ein Problem haben, dass remove() sowohl überlastet ist mit int und Object, während get() nur ein int nimmt. Versuchen Sie remove(toRemove.get(i).intValue()).

remove(Object) von AbstractCollection wird durch die Liste suchen und das entsprechende Objekt entfernen, die dort nicht sein, weil Sie es ein Integer und die Liste senden nur JCheckBox s. Sie versuchen, remove(int) aufzurufen, aber da Sie es Integer geben, wird stattdessen die Objektüberladung aufgerufen. Durch die Umwandlung der Integer in eine int vermeiden Sie dieses Problem

Auch können Sie immer sicher sein, dass die ID in toRemove immer gleich dem Index ist? Wenn toRemove nicht in der Reihenfolge der größten und der kleinsten ist, wird es nicht sein.

+0

Danke - das hat funktioniert! Und ja, wenn ich toRemove baue, bin ich sicher, dass es in Ordnung ist, so dass ich, wenn ich in umgekehrter Reihenfolge darüber gehe, die Indizes nicht anpassen muss, wenn Elemente entfernt werden. – zigdon

+0

Diese Antwort berücksichtigt keine 'NULL' Objekte – Salman

+0

@Salman Die Frage impliziert, dass es keine' null's gibt. Wenn es eine "Null" gibt, würde die Zeile über dem 'remove()' -Aufruf einen Nullzeiger werfen, während das Argument zum äußeren 'get()' -Aufruf entpackt wird. – ILMTitan

1

Es gibt zwei Probleme mit Ihrem Code. Zuerst wird die falsche toRemove-Methode aufgerufen. Wenn Sie "toRemove.get (i)" aufrufen, wird der Rückgabewert in einem java.lang.Integer anstelle von einem int autoboxed. Daher wird java.util.List # remove (Object) anstelle von java.util.List # remove (int) aufgerufen. Es versucht ein Integer-Objekt zu entfernen und gibt false zurück. Wenn Sie Integer auf einen Int-Wert anwenden, wird die gewünschte Methode aufgerufen.

Zweites Problem: Jedes Mal, wenn Sie ein Element der Liste entfernen, ändern sich die Indizes aller nachfolgenden Elemente, wenn diese Elemente "verschoben" werden. Es gibt mehrere Möglichkeiten, dies zu umgehen. Eine besteht darin, Ihre Indexliste in absteigender Reihenfolge zu sortieren. Eine andere wäre, eine Reihe von Indizes zu verwenden, ein neues Array zu erstellen und nur diejenigen Elemente in das neue Array zu kopieren, deren Index nicht in der Menge enthalten ist.

Verwandte Themen