Перед Java 8 вы должны использовать:
tourists.removeAll(Collections.singleton(null));
Использование после Java 8:
tourists.removeIf(Objects::isNull);
Причина здесь в сложности времени. Проблема с массивами состоит в том, что операция удаления может занять O (n) времени для завершения. На самом деле в Java это копия массива оставшихся элементов, перемещаемых для замены пустого места. Многие другие решения, предлагаемые здесь, вызовут эту проблему. С технической точки зрения первый O (n * m), где m равно 1, потому что это одиночный ноль: поэтому O (n)
Вы должны удалить все синглтоны, внутренне это выполняет batchRemove (), который имеет позицию чтения и позицию записи. И повторяет список. Когда он достигает нуля, он просто повторяет позицию чтения на 1. Когда они одинаковы, он проходит, когда они отличаются, он продолжает двигаться, копируя значения. Тогда в конце это урезает к размеру.
Это эффективно делает это внутренне:
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 (n).
Единственное, что может быть быстрее, - это если вы перебираете список с обоих концов, и когда вы находите ноль, вы устанавливаете его значение равным значению, которое вы нашли в конце, и уменьшаете его. Итерировали, пока два значения не совпали. Вы бы испортили порядок, но значительно сократили бы количество установленных вами значений по сравнению с теми, которые вы оставили в покое. Это хороший способ узнать, но он не сильно поможет, поскольку .set () в основном бесплатен, но эта форма удаления является полезным инструментом для вашего пояса.
for (Iterator<Tourist> itr = tourists.iterator(); itr.hasNext();) {
if (itr.next() == null) { itr.remove(); }
}
Хотя это кажется достаточно разумным, .remove () внутри итератора вызывает:
ArrayList.this.remove(lastRet);
Что снова является операцией O (n) при удалении. Он выполняет System.arraycopy (), что опять-таки не то, что вам нужно, если вы заботитесь о скорости. Это делает это п ^ 2.
Есть также:
while(tourists.remove(null));
Который есть O (m * n ^ 2). Здесь мы не только перебираем список. Мы повторяем весь список, каждый раз, когда мы совпадаем с нулем. Затем мы делаем n / 2 (средние) операции, чтобы выполнить System.arraycopy () для удаления. Вы можете буквально отсортировать всю коллекцию между элементами со значениями и элементами с нулевыми значениями и обрезать окончание за меньшее время. На самом деле, это верно для всех сломанных. По крайней мере теоретически, фактическая system.arraycopy на самом деле не является операцией N на практике. В теории теория и практика - это одно и то же; на практике это не так.
Iterator
? Копай ява-док. download.oracle.com/javase/6/docs/api/java/util/...