it-swarm.com.de

Wie entferne ich alle Nullelemente aus einer ArrayList oder einem String-Array?

Ich versuche es mit einer Schleife so

// ArrayList tourists

for (Tourist t : tourists) {
    if (t != null) {     
        t.setId(idForm); 
    }   
}

Aber es ist nicht schön. Kann mir jemand eine bessere Lösung vorschlagen? 


Einige nützliche Benchmarks, um eine bessere Entscheidung zu treffen: 

While-Schleife, für Schleifen- und Iteratorleistungstest

169

Versuchen:

tourists.removeAll(Collections.singleton(null));

Lesen Sie die Java API . Der Code gibt Java.lang.UnsupportedOperationException für unveränderliche Listen aus (z. B. erstellt mit Arrays.asList). Siehe diese Antwort für weitere Details.

343
Lithium

Ab 2015 ist dies der beste Weg (Java 8):

tourists.removeIf(Objects::isNull);

Hinweis: Dieser Code löst Java.lang.UnsupportedOperationException für Listen fester Größe aus (z. B. mit Arrays.asList erstellt), einschließlich unveränderlicher Listen.

95
MarcG
list.removeAll(Collections.singleton(null));

Es wird UnsupportedException ausgelöst, wenn Sie es für Arrays.asList verwenden, da Sie Immutable copy erhalten, damit es nicht geändert werden kann. Siehe den Code. Es erstellt Mutable copy und löst keine Ausnahme aus.

public static String[] clean(final String[] v) {
    List<String> list = new ArrayList<String>(Arrays.asList(v));
    list.removeAll(Collections.singleton(null));
    return list.toArray(new String[list.size()]);
}
44
AZ_

Nicht effizient, aber kurz

while(tourists.remove(null));
18
Peter Lawrey

Wenn Sie unveränderliche Datenobjekte bevorzugen oder einfach nicht destruktiv für die Eingabeliste sein möchten, können Sie Guavas Prädikate verwenden.

ImmutableList.copyOf(Iterables.filter(tourists, Predicates.notNull()))
18
James Kojo
 for (Iterator<Tourist> itr = tourists.iterator(); itr.hasNext();) {
      if (itr.next() == null) { itr.remove(); }
 }
7
Mat Mannion

Die Objects-Klasse hat eine nonNullPredicate, die mit filter verwendet werden kann.

Zum Beispiel:

tourists.stream().filter(Objects::nonNull).collect(Collectors.toList());
3
JeffF

Mit Java 8 können Sie dies mit stream() und filter() tun.

tourists = tourists.stream().filter(t -> t != null).collect(Collectors.toList())

oder

tourists = tourists.stream().filter(Objects::nonNull).collect(Collectors.toList())

Für weitere Informationen: Java 8 - Streams

3
Jad Chahine

Vor Java 8 sollten Sie verwenden:

tourists.removeAll(Collections.singleton(null));

Verwendung nach Java 8:

tourists.removeIf(Objects::isNull);

Der Grund ist die zeitliche Komplexität. Das Problem bei Arrays ist, dass ein Entfernungsvorgang O(n) Zeit in Anspruch nehmen kann. In Java ist dies eine Array-Kopie der verbleibenden Elemente, die verschoben werden, um die leere Stelle zu ersetzen. Viele andere hier angebotene Lösungen lösen dieses Problem aus. Ersteres ist technisch O (n * m), wobei m 1 ist, weil es eine Singleton-Null ist: also O (n)

Sie solltenAll des Singleton entfernen, intern wird ein batchRemove () ausgeführt, der über eine Leseposition und eine Schreibposition verfügt. Und iteriert die Liste. Wenn es eine Null trifft, iteriert es einfach die Leseposition um 1. Wenn sie gleich sind, werden sie weitergegeben, wenn sie unterschiedlich sind, bewegt sie sich weiter und kopiert die Werte. Am Ende wird es auf die gewünschte Größe zugeschnitten.

Es tut dies effektiv intern:

public static <E> void removeNulls(ArrayList<E> list) {
    int size = list.size();
    int read = 0;
    int write = 0;
    for (; read < size; read++) {
        E element = list.get(read);
        if (element == null) continue;
        if (read != write) list.set(write, element);
        write++;
    }
    if (write != size) {
        list.subList(write, size).clear();
    }
}

Was Sie explizit sehen können, ist eine O(n) - Operation.

Das einzige, was schneller sein könnte, ist, wenn Sie die Liste von beiden Seiten durchlaufen und wenn Sie eine Null gefunden haben, setzen Sie ihren Wert auf den Wert, den Sie am Ende gefunden haben, und dekrementiert diesen Wert. Und iteriert, bis die beiden Werte übereinstimmen. Sie würden die Reihenfolge durcheinander bringen, würden jedoch die Anzahl der Werte, die Sie festlegen, gegenüber den Werten, die Sie alleine gelassen haben, erheblich reduzieren. Dies ist eine gute Methode, um zu wissen, hilft aber nicht viel, da .set () grundsätzlich kostenlos ist, aber diese Form des Löschens ist ein nützliches Werkzeug für Ihren Gürtel.


for (Iterator<Tourist> itr = tourists.iterator(); itr.hasNext();) {
      if (itr.next() == null) { itr.remove(); }
 }

Während dies vernünftig erscheint, ruft die .remove () auf dem Iterator intern auf:

ArrayList.this.remove(lastRet);

Dies ist wiederum die Operation O(n) in der Remove-Funktion. Es macht eine System.arraycopy (), die wiederum nicht das ist, was Sie möchten, wenn Sie auf Geschwindigkeit achten. Das macht es n ^ 2.

Es gibt auch:

while(tourists.remove(null));

Welches ist O (m * n ^ 2). Hier durchlaufen wir nicht nur die Liste. Wir wiederholen die gesamte Liste jedes Mal, wenn wir mit der Null übereinstimmen. Dann führen wir n/2 (Durchschnitt) -Operationen durch, um System.arraycopy () auszuführen, um das Entfernen durchzuführen ..__ Sie können die gesamte Auflistung buchstäblich nach Elementen mit Werten und Elementen mit Nullwerten sortieren und die Endung in less reduzieren Zeit. In der Tat gilt das für alle gebrochenen. Zumindest theoretisch ist die eigentliche system.arraycopy in der Praxis keine N-Operation. Theoretisch sind Theorie und Praxis dasselbe; In der Praxis sind sie nicht.

3
Tatarize

Es gibt eine einfache Möglichkeit, alle null-Werte aus collection zu entfernen. Sie müssen eine Sammlung mit null als Parameter an die removeAll()-Methode übergeben

List s1=new ArrayList();
s1.add(null);

yourCollection.removeAll(s1);
3
shiv

Dies ist eine einfache Methode, um Standard-Nullwerte aus der Arrayliste zu entfernen

     tourists.removeAll(Arrays.asList(null));  

ansonsten Stringwert "null" aus Arrayliste entfernen

       tourists.removeAll(Arrays.asList("null"));  
2
Jobin_vibes

Ich habe die Streamschnittstelle zusammen mit der Streamoperation collect und einer Helper-Methode verwendet, um eine neue Liste zu erstellen.

tourists.stream().filter(this::isNotNull).collect(Collectors.toList());

private <T> boolean isNotNull(final T item) {
    return  item != null;
}
1
Mabi

Wir können den Iterator dafür verwenden, um alle Nullwerte zu entfernen.

Iterator<Tourist> itr= tourists.iterator();
while(itr.hasNext()){
    if(itr.next() == null){
        itr.remove();
    }
}
1
amit

Ich habe damit herumgespielt und herausgefunden, dass trimToSize () zu funktionieren scheint. Ich arbeite an der Android-Plattform, daher könnte es anders sein.

1
theblitz

Ähnlich wie bei @Lithium, es wird jedoch kein Fehler ausgegeben: "Liste enthält möglicherweise keinen Typ Null":

   list.removeAll(Collections.<T>singleton(null));
List<String> colors = new ArrayList<>(
Arrays.asList("RED", null, "BLUE", null, "GREEN"));
// using removeIf() + Objects.isNull()
colors.removeIf(Objects::isNull);
0
cunhaf

Mit Java 8 kann dies auf verschiedene Arten mit Streams, parallelen Streams und removeIf-Methode durchgeführt werden:

List<String> stringList = new ArrayList<>(Arrays.asList(null, "A", "B", null, "C", null));
List<String> listWithoutNulls1 = stringList.stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toList()); //[A,B,C]
List<String> listWithoutNulls2 = stringList.parallelStream()
                .filter(Objects::nonNull)
                .collect(Collectors.toList()); //[A,B,C]
stringList.removeIf(Objects::isNull); //[A,B,C]

Der parallele Stream nutzt verfügbare Prozessoren und beschleunigt den Prozess für Listen mit angemessener Größe. Es ist immer ratsam, vor der Verwendung von Streams ein Benchmarking durchzuführen.

0
i_am_zero