wake-up-neo.net

Eine Ganzzahl ordnungsgemäß aus einer Liste <Ganzzahl> entfernen

Hier ist eine schöne Fallgrube, der ich gerade begegnet bin ... Eine Liste von ganzen Zahlen:

List<Integer> list = new ArrayList<Integer>();
list.add(5);
list.add(6);
list.add(7);
list.add(1);

Irgendwelche fundierte Vermutung, was passiert, wenn Sie list.remove(1) ausführen? Was ist mit list.remove(new Integer(1))? Dies kann zu bösen Fehlern führen.

Was ist der richtige Weg, um zwischen remove(int index) zu unterscheiden, das ein Element aus dem angegebenen Index entfernt, und remove(Object o) , das ein Element durch Verweis entfernt, wenn es sich um Listen von Ganzzahlen handelt?


Der wichtigste Punkt, der hier zu berücksichtigen ist, ist der eine @Nikita-Parameter - der exakte Parameterabgleich hat Vorrang vor dem automatischen Boxen.

184
Yuval Adam

Java ruft immer die Methode auf, die am besten zu Ihrem Argument passt. Auto-Boxing und implizites Upcasting werden nur durchgeführt, wenn es keine Methode gibt, die ohne Casting/Auto-Boxing aufgerufen werden kann.

Die List-Schnittstelle gibt zwei Methoden zum Entfernen an (bitte beachten Sie die Benennung der Argumente):

  • remove(Object o)
  • remove(int index)

Das bedeutet, dass list.remove(1) das Objekt an Position 1 entfernt und remove(new Integer(1)) das erste Vorkommen des angegebenen Elements aus dieser Liste entfernt.

217
aka

Sie können Gießen verwenden

list.remove((int) n);

und

list.remove((Integer) n);

Es ist egal, ob n ein Int oder Integer ist, die Methode ruft immer die erwartete auf.

Die Verwendung von (Integer) n oder Integer.valueOf(n) ist effizienter als new Integer(n), da die ersten beiden den Integer-Cache verwenden können, während der spätere immer ein Objekt erstellt.

63
Peter Lawrey

Ich weiß nicht, wie man "richtig" ist, aber die von Ihnen vorgeschlagene Methode funktioniert gut:

list.remove(int_parameter);

entfernt das Element an der angegebenen Position und

list.remove(Integer_parameter);

entfernt das angegebene Objekt aus der Liste.

Dies liegt daran, dass VM zunächst versucht, eine Methode zu finden, die mit genau dem gleichen Parametertyp deklariert ist, und versucht dann nur Autoboxing.

10
Nikita Rybak

list.remove(4) ist eine exakte Übereinstimmung von list.remove(int index), daher wird es aufgerufen. Wenn Sie list.remove(Object) aufrufen möchten, gehen Sie wie folgt vor: list.remove((Integer)4).

7
Petar Minchev

Irgendwelche fundierte Vermutung, was passiert, wenn Sie list.remove ausführen (1)? Was ist mit list.remove (new Integer (1))?

Man muss nicht raten. Im ersten Fall wird List.remove(int) aufgerufen, und das Element an Position 1 wird entfernt. Im zweiten Fall wird List.remove(Integer) aufgerufen, und das Element, dessen Wert gleich Integer(1) ist, wird entfernt. In beiden Fällen wählt der Java-Compiler die nächste passende Überladung aus.

Ja, hier gibt es Verwirrung (und Fehler), aber es ist ein ziemlich ungewöhnlicher Anwendungsfall.

Wenn die beiden List.remove-Methoden in Java 1.2 definiert wurden, waren die Überladungen nicht mehrdeutig. Das Problem trat nur bei der Einführung von Generics und Autoboxing in Java 1.5 auf. Im Nachhinein wäre es besser gewesen, wenn eine der Entfernungsmethoden einen anderen Namen erhalten hätte. Aber jetzt ist es zu spät.

4
Stephen C

Beachten Sie, dass Sie selbst dann, wenn VM nicht das Richtige getan hat, das richtige Verhalten erzielen kann, indem Sie die Tatsache verwenden, dass remove(Java.lang.Object) auf beliebige Objekte wirkt:

myList.remove(new Object() {
  @Override
  public boolean equals(Object other) {
    int k = ((Integer) other).intValue();
    return k == 1;
  }
}
2
user268396

Ich habe einfach gerne wie von #decitrig in akzeptierter Antwort vorgeschlagen vorgeschlagen.

list.remove(Integer.valueOf(intereger_parameter));

Das hat mir geholfen. Vielen Dank nochmal #decitrig für deinen Kommentar. Es kann für jemanden helfen.

1
Shylendra Madda

Nun, hier ist der Trick.

Nehmen wir zwei Beispiele an:

public class ArrayListExample {

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

    collection.add(1);
    collection.add(2);
    collection.add(3);
    collection.add(null);
    collection.add(4);
    collection.add(null);
    System.out.println("Collection" + collection);

    arrayList.add(1);
    arrayList.add(2);
    arrayList.add(3);
    arrayList.add(null);
    arrayList.add(4);
    arrayList.add(null);
    System.out.println("ArrayList" + arrayList);

    collection.remove(3);
    arrayList.remove(3);
    System.out.println("");
    System.out.println("After Removal of '3' :");
    System.out.println("Collection" + collection);
    System.out.println("ArrayList" + arrayList);

    collection.remove(null);
    arrayList.remove(null);
    System.out.println("");
    System.out.println("After Removal of 'null': ");
    System.out.println("Collection" + collection);
    System.out.println("ArrayList" + arrayList);

  }

}

Nun sehen wir uns die Ausgabe an:

Collection[1, 2, 3, null, 4, null]
ArrayList[1, 2, 3, null, 4, null]

After Removal of '3' :
Collection[1, 2, null, 4, null]
ArrayList[1, 2, 3, 4, null]

After Removal of 'null': 
Collection[1, 2, 4, null]
ArrayList[1, 2, 3, 4]

Jetzt analysieren wir die Ausgabe:

  1. Wenn 3 aus der Auflistung entfernt wird, ruft es die remove()-Methode der Auflistung auf, die Object o als Parameter verwendet. Daher wird das Objekt 3..__ entfernt. In arrayList wird es jedoch durch den Index 3 überschrieben, und daher wird das vierte Element entfernt. 

  2. Durch die gleiche Logik der Objektentfernung wird in der zweiten Ausgabe in beiden Fällen Null entfernt.

Um die Zahl 3 zu entfernen, die ein Objekt ist, müssen wir explizit 3 als object übergeben.

Dies kann durch Casting oder Wrapping mit der Wrapper-Klasse Integer erfolgen.

Z.B: 

Integer removeIndex = Integer.valueOf("3");
collection.remove(removeIndex);
0
Pritam Banerjee