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



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



// ArrayList tourists

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


но это не приятно. Может кто-нибудь предложить мне лучшее решение?





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



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

1072   16  

16 ответов:

попробуй:

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

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

по состоянию на 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()]);
}

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

while(tourists.remove(null));

Если вы предпочитаете неизменяемые объекты данных, или если вы просто не хотите быть разрушительным для входного списка, вы можете использовать предикаты 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

    Ничего не найдено.