Как удалить все нулевые элементы из массива 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]

Параллельный поток будет использовать доступные процессоры и ускорит процесс для списков разумного размера. Всегда рекомендуется проводить тесты перед использованием потоков.