Как удалить все нулевые элементы из массива ArrayList или String?
Я пытаюсь с петлей, как это
// ArrayList tourists
for (Tourist t : tourists) {
if (t != null) {
t.setId(idForm);
}
}
но это не приятно. Может кто-нибудь предложить мне лучшее решение?
некоторые полезные ориентиры для принятия лучшего решения:
в то время как цикл, для цикла и итератора тест производительности
16 ответов:
по состоянию на 2015 год, это лучший способ (Java 8):
tourists.removeIf(Objects::isNull);Примечание: этот код будет бросать
java.lang.UnsupportedOperationExceptionдля списков фиксированного размера(например, созданных с помощью массивов.asList), включая неизменяемые списки.
list.removeAll(Collections.singleton(null));Он бросает UnsupportedException если вы используете его на массивы.asList, потому что это дает вам неизменяемые копировать, поэтому он не может быть изменен. Смотрите ниже код. Он создает Mutable копировать и не будет бросать никаких исключений.
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()]); }
Если вы предпочитаете неизменяемые объекты данных, или если вы просто не хотите быть разрушительным для входного списка, вы можете использовать предикаты Guava.
ImmutableList.copyOf(Iterables.filter(tourists, Predicates.notNull()))
for (Iterator<Tourist> itr = tourists.iterator(); itr.hasNext();) { if (itr.next() == null) { itr.remove(); } }
существует простой способ удаления всех
nullзначенияcollection.Вы должны передать коллекцию, содержащую null в качестве параметраremoveAll()методList s1=new ArrayList(); s1.add(null); yourCollection.removeAll(s1);
The
ObjectsклассnonNullPredicateЭто можно использовать сfilter.например:
tourists.stream().filter(Objects::nonNull).collect(Collectors.toList());
используете Java 8, вы можете сделать это с помощью
stream()иfilter()tourists = tourists.stream().filter(t -> t != null).collect(Collectors.toList())или
tourists = tourists.stream().filter(Objects::nonNull).collect(Collectors.toList())дополнительная информация : Java 8-Streams
это простой способ удалить значения null по умолчанию из arraylist
tourists.removeAll(Arrays.asList(null));в противном случае строковое значение "null" удалить из arraylist
tourists.removeAll(Arrays.asList("null"));
Я поиграл с этим и узнал, что trimToSize (), кажется, работает. Я работаю на платформе Android, так что это может быть по-другому.
мы можем использовать итератор для того же, чтобы удалить все нулевые значения.
Iterator<Tourist> itr= tourists.iterator(); while(itr.hasNext()){ if(itr.next() == null){ itr.remove(); } }
я использовал интерфейс потока вместе с операцией потока собрать и вспомогательный метод для создания нового списка.
tourists.stream().filter(this::isNotNull).collect(Collectors.toList()); private <T> boolean isNotNull(final T item) { return item != null; }
Pre-Java 8 вы должны использовать:
tourists.removeAll(Collections.singleton(null));Post-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) операция.
единственное, что может быть быстрее, - это если вы повторяете список с обоих концов, и когда вы нашли null, вы устанавливаете его значение равным значению, которое вы нашли в конце, и уменьшаете это значение. И повторяется до тех пор, пока два значения не совпадут. Вы испортили бы порядок, но значительно уменьшили бы количество значений вы устанавливаете против тех, кого вы оставили в покое. Что это хороший способ знаю, но не поможет здесь .set () в основном бесплатно, но эта форма удаления является полезной инструмент для вашего пояса.
for (Iterator<Tourist> itr = tourists.iterator(); itr.hasNext();) { if (itr.next() == null) { itr.remove(); } }хотя это кажется достаточно разумным, то .remove () на итераторе внутренне вызывает:
ArrayList.this.remove(lastRet);который снова является операцией O(n) в remove. Он делает систему.arraycopy (), но это опять не то, что вы хотите, если вы заботитесь о скорости. Это делает его n^2.
есть:
while(tourists.remove(null));который является O (m*n^2). Здесь мы не только повторяем список. Мы повторяем весь список, каждый раз, когда мы соответствуем ноль. Затем мы делаем n / 2 (средние) операции, чтобы сделать систему.arraycopy() для выполнения удаления. Вы можете буквально отсортировать всю коллекцию между элементами со значениями и элементами с нулевыми значениями и обрезать окончание за меньшее время. На самом деле, это верно для всех сломанных. По крайней мере в теории, в реальной системе.arraycopy на самом деле не является операцией N на практике. В теории, теории и практике это одно и то же; на практике это не так.
используя Java 8 это может быть выполнено различными способами с использованием потоков, параллельных потоков и
removeIfспособ: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]параллельный поток будет использовать доступные процессоры и ускорит процесс для разумного размера списков. Всегда рекомендуется проводить бенчмарк перед использованием потоков.
похоже на @ Lithium ответ, но не бросает" список не может содержать тип null " ошибка:
list.removeAll(Collections.<T>singleton(null));
Comments