Avant Java 8, vous devez utiliser:
tourists.removeAll(Collections.singleton(null));
Utilisation post-Java 8:
tourists.removeIf(Objects::isNull);
La raison ici est la complexité du temps. Le problème avec les tableaux est qu'une opération de suppression peut prendre du temps O (n). En réalité, en Java, il s'agit d'une copie de tableau des éléments restants déplacés pour remplacer l'emplacement vide. De nombreuses autres solutions proposées ici déclencheront ce problème. Le premier est techniquement O (n * m) où m vaut 1 car c'est un singleton nul: donc O (n)
Vous devriez removeAll du singleton, en interne, il fait un batchRemove () qui a une position de lecture et une position d'écriture. Et répète la liste. Lorsqu'il atteint une valeur nulle, il itère simplement la position de lecture de 1. Quand ils sont identiques, il passe, quand ils sont différents, il continue à copier les valeurs. Puis à la fin, il s'adapte à la taille.
Il le fait efficacement en interne:
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();
}
}
Ce que vous pouvez voir explicitement est une opération O (n).
La seule chose qui pourrait jamais être plus rapide est si vous avez itéré la liste des deux extrémités, et lorsque vous avez trouvé un null, vous définissez sa valeur égale à la valeur que vous avez trouvée à la fin et décrémentez cette valeur. Et itéré jusqu'à ce que les deux valeurs correspondent. Vous gâcheriez l'ordre, mais réduiriez considérablement le nombre de valeurs que vous définissez par rapport à celles que vous avez laissées seules. Ce qui est une bonne méthode à connaître mais qui n'aidera pas beaucoup ici car .set () est fondamentalement gratuit, mais cette forme de suppression est un outil utile pour votre ceinture.
for (Iterator<Tourist> itr = tourists.iterator(); itr.hasNext();) {
if (itr.next() == null) { itr.remove(); }
}
Bien que cela semble assez raisonnable, le .remove () sur l'itérateur appelle en interne:
ArrayList.this.remove(lastRet);
Ce qui est encore l'opération O (n) dans l'enlèvement. Il fait un System.arraycopy () qui n'est pas non plus ce que vous voulez, si vous vous souciez de la vitesse. Cela en fait n ^ 2.
Il y a aussi:
while(tourists.remove(null));
Qui est O (m * n ^ 2). Ici, nous ne faisons pas qu'itérer la liste. Nous réitérons la liste entière, chaque fois que nous correspondons à la valeur nulle. Ensuite, nous effectuons n / 2 (moyennes) opérations pour faire le System.arraycopy () pour effectuer la suppression. Vous pouvez littéralement trier toute la collection entre les éléments avec des valeurs et les éléments avec des valeurs nulles et couper la fin en moins de temps. En fait, c'est vrai pour tous les cassés. Au moins en théorie, le system.arraycopy réel n'est pas réellement une opération N en pratique. En théorie, théorie et pratique sont la même chose; en pratique, ils ne le sont pas.
Iterator
? Creusez java-doc. download.oracle.com/javase/6/docs/api/java/util/…