Antes do Java 8, você deve usar:
tourists.removeAll(Collections.singleton(null));
Uso pós-Java 8:
tourists.removeIf(Objects::isNull);
A razão aqui é a complexidade do tempo. O problema com matrizes é que uma operação de remoção pode levar O (n) tempo para ser concluída. Realmente em Java, esta é uma cópia da matriz dos elementos restantes sendo movidos para substituir o ponto vazio. Muitas outras soluções oferecidas aqui acionarão esse problema. O primeiro é tecnicamente O (n * m) onde m é 1 porque é um nulo único: então O (n)
Você deve remover All do singleton, internamente ele faz um batchRemove () que possui uma posição de leitura e uma posição de gravação. E itera a lista. Quando atinge um nulo, ele simplesmente itera a posição de leitura em 1. Quando eles são os mesmos que passam, quando são diferentes, ele continua se movendo ao copiar os valores. Então, no final, apara ao tamanho.
Ele efetivamente faz isso internamente:
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();
}
}
O que você pode ver explicitamente é uma operação O (n).
A única coisa que poderia ser mais rápida é se você iterasse a lista dos dois extremos e, quando encontrasse um nulo, defina seu valor igual ao valor encontrado no final e diminua esse valor. E iterou até que os dois valores correspondessem. Você estragaria o pedido, mas reduziria muito o número de valores que você definiu versus os que você deixou sozinho. Qual é um bom método para saber, mas não ajudará muito aqui, pois .set () é basicamente gratuito, mas essa forma de exclusão é uma ferramenta útil para o seu cinto.
for (Iterator<Tourist> itr = tourists.iterator(); itr.hasNext();) {
if (itr.next() == null) { itr.remove(); }
}
Embora isso pareça bastante razoável, o .remove () no iterador chama internamente:
ArrayList.this.remove(lastRet);
Qual é novamente a operação O (n) na remoção. Ele faz um System.arraycopy () que novamente não é o que você deseja, se você se preocupa com a velocidade. Isso torna n ^ 2.
Há também:
while(tourists.remove(null));
Qual é O (m * n ^ 2). Aqui, não apenas iteramos a lista. Reiteramos a lista inteira, sempre que correspondermos ao nulo. Em seguida, fazemos n / 2 (médias) operações para executar o System.arraycopy () para executar a remoção. Você poderia literalmente ordenar a coleção inteira entre itens com valores e itens com valores nulos e aparar o final em menos tempo. De fato, isso é verdade para todos os quebrados. Pelo menos em teoria, o system.arraycopy real não é realmente uma operação N na prática. Em teoria, teoria e prática são a mesma coisa; na prática eles não são.
Iterator
? Dig java-doc. Você está em