it-swarm.com.ru

Как удалить все нулевые элементы из ArrayList или String Array?

Я пытаюсь с такой петлей

// ArrayList tourists

for (Tourist t : tourists) {
    if (t != null) {     
        t.setId(idForm); 
    }   
}

Но это не Ницца. Кто-нибудь может предложить мне лучшее решение? 


Некоторые полезные ориентиры для принятия лучшего решения: 

цикл while, цикл For и тест производительности итератора

169
Enrique Juan de Dios

Пытаться:

tourists.removeAll(Collections.singleton(null));

Прочитайте Java API . Код выдаст Java.lang.UnsupportedOperationException для неизменяемых списков (например, созданных с помощью Arrays.asList); смотрите этот ответ для более подробной информации.

343
Lithium

По состоянию на 2015 год это лучший способ (Java 8):

tourists.removeIf(Objects::isNull);

Примечание: Этот код будет генерировать Java.lang.UnsupportedOperationException для списков фиксированного размера (например, созданных с помощью Arrays.asList), включая неизменяемые списки.

95
MarcG
list.removeAll(Collections.singleton(null));

Он выбрасывает UnsupportedException , если вы используете его в Arrays.asList, потому что он дает вам неизменяемую копию, поэтому его нельзя изменить. Смотрите ниже код. Он создает Mutable copy и не будет выдавать никаких исключений.

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()]);
}
44
AZ_

Не эффективно, но коротко

while(tourists.remove(null));
18
Peter Lawrey

Если вы предпочитаете неизменяемые объекты данных или просто не хотите быть разрушительными для списка ввода, вы можете использовать предикаты Guava.

ImmutableList.copyOf(Iterables.filter(tourists, Predicates.notNull()))
18
James Kojo
 for (Iterator<Tourist> itr = tourists.iterator(); itr.hasNext();) {
      if (itr.next() == null) { itr.remove(); }
 }
7
Mat Mannion

Класс Objects имеет nonNullPredicate, который можно использовать с filter.

Например:

tourists.stream().filter(Objects::nonNull).collect(Collectors.toList());
3
JeffF

Используя 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

3
Jad Chahine

До 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-операцией. В теории теория и практика - это одно и то же; на практике это не так.

3
Tatarize

Существует простой способ удаления всех значений null из collection. Необходимо передать коллекцию, содержащую null, в качестве параметра методу removeAll()

List s1=new ArrayList();
s1.add(null);

yourCollection.removeAll(s1);
3
shiv

Это простой способ удалить нулевые значения по умолчанию из массива

     tourists.removeAll(Arrays.asList(null));  

в противном случае строковое значение "null" удалить из массива

       tourists.removeAll(Arrays.asList("null"));  
2
Jobin_vibes

Я использовал интерфейс потока вместе с операцией потока collect и вспомогательным методом для создания нового списка.

tourists.stream().filter(this::isNotNull).collect(Collectors.toList());

private <T> boolean isNotNull(final T item) {
    return  item != null;
}
1
Mabi

Мы можем использовать итератор для того же самого, чтобы удалить все нулевые значения.

Iterator<Tourist> itr= tourists.iterator();
while(itr.hasNext()){
    if(itr.next() == null){
        itr.remove();
    }
}
1
amit

Я поиграл с этим и обнаружил, что trimToSize (), кажется, работает. Я работаю на платформе Android, поэтому она может отличаться.

1
theblitz

Аналогичен ответу @Lithium, но не выдает ошибку «Список может не содержать тип null»:

   list.removeAll(Collections.<T>singleton(null));
0
Hannah Louisa Carney
List<String> colors = new ArrayList<>(
Arrays.asList("RED", null, "BLUE", null, "GREEN"));
// using removeIf() + Objects.isNull()
colors.removeIf(Objects::isNull);
0
cunhaf

Используя 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]

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

0
i_am_zero