Удалить объекты из ArrayList на основе заданных критериев

java arraylist

15707 просмотра

7 ответа

Я хотел бы удалить элемент из ArrayListJava, если он соответствует определенным критериям.

то есть:

for (Pulse p : pulseArray) {
    if (p.getCurrent() == null) {
        pulseArray.remove(p);
    }
}

Я могу понять, почему это не работает, но какой хороший способ сделать это?

Автор: user1724416 Источник Размещён: 12.11.2019 09:21

Ответы (7)


19 плюса

Решение

Вы должны использовать Iteratorдля итерации и removeфункцию итератора (не из списка):

Iterator<Pulse> iter = pulseArray.iterator();
while (iter.hasNext()) {
  Pulse p = iter.next();
  if (p.getCurrent()==null) iter.remove();
}

Обратите внимание , что # удалить Итератор функция называется optionnal , но будет реализован итератора в ArrayList в.

Вот код этой конкретной функции из ArrayList.java:

765         public void remove() {
766             if (lastRet < 0)
767                 throw new IllegalStateException();
768             checkForComodification();
769 
770             try {
771                 ArrayList.this.remove(lastRet);
772                 cursor = lastRet;
773                 lastRet = -1;
774                 expectedModCount = modCount;
775             } catch (IndexOutOfBoundsException ex) {
776                 throw new ConcurrentModificationException();
777             }
778         }
779 
780         final void checkForComodification() {
781             if (modCount != expectedModCount)
782                 throw new ConcurrentModificationException();
783         }
784     }

expectedModCount = modCount;Линия поэтому он не будет бросать исключение , если вы используете его в то время итерации.

Автор: Denys Séguret Размещён: 09.11.2012 09:57

18 плюса

Вы можете использовать Collection :: removeIf (фильтр предикатов) (доступно с Java8 и далее), вот простой пример:

final Collection<Integer> list = new ArrayList<>(Arrays.asList(1, 2));
list.removeIf(value -> value < 2);
System.out.println(list); // outputs "[2]"
Автор: Markus Schulte Размещён: 15.12.2017 01:53

3 плюса

Не нужно использовать итератор. С Java 8 (возможности потоковой передачи и фильтрации и лямбда-выражения) вы можете выполнить это, используя одну строку. Например, требуемый код, который выполняет указанную вами операцию:

pulseArray = pulseArray.stream().filter(pulse -> pulse != null).collect(Collectors.toList());
Автор: Rajarshee Mitra Размещён: 10.10.2015 02:32

2 плюса

Когда вы удаляете элемент из того же списка , индекс нарушается. Попробуйте немного иначе, как показано ниже:

  for (int i=0; i < pulseArray.size(); i++) {
     Pulse p = (Pulse)pulseArray.get(i);
     if (p.getCurrent() == null) {
        pulseArray.remove(p);
        i--;//decrease the counter by one
     }
  }
Автор: Yogendra Singh Размещён: 09.11.2012 10:02

2 плюса

В качестве альтернативы использованию итератора вы можете использовать библиотеку коллекций Guava . Это имеет преимущество в том, что он более функциональный (если вам нравятся такие вещи):

Predicate<Pulse> hasCurrent = new Predicate<Pulse>() {
  @Override public boolean apply(Pulse input) {
    return (input.getCurrent() != null);
  }
};

pulseArray = Lists.newArrayList(Collections2.filter(pulseArray, hasCurrent));
Автор: dbyrne Размещён: 09.11.2012 11:11

0 плюса

Вы не можете изменить коллекцию, через которую вы проходите, используя методы коллекции. Однако некоторые итераторы (включая итераторы для ArrayLists) поддерживают remove()метод, который позволяет вам удалять методы в том порядке, в котором вы выполняете итерацию.

Iterator<Pulse> iterator = pulseArray.iterator();
while (iterator.hasNext()) {
  Pulse p = iterator.next();
  if (p.getCurrent() == null) {
    iterator.remove();
  }
}
Автор: Simon Nickerson Размещён: 09.11.2012 09:59

-1 плюса

Использование итератора даст вам возможность изменять список при переборе массива

Автор: Kakarot Размещён: 09.11.2012 10:39
Вопросы из категории :
32x32