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