Удалить элементы из коллекции во время итерации
AFAIK, есть два подхода:
Есть ли причины предпочитать один подход другому (например, предпочтение первого подхода по простой причине читабельности)?
Предположим, у нас есть следующая коллекция книг
Собрать и удалить
Первый метод состоит в том, чтобы собрать все объекты, которые мы хотим удалить (например, используя расширенный цикл for), и после того, как мы закончим итерацию, мы удалим все найденные объекты.
Это предполагает, что операция, которую вы хотите сделать, это «удалить».
Если вы хотите «добавить» этот подход, он также будет работать, но я предполагаю, что вы переберите другую коллекцию, чтобы определить, какие элементы вы хотите добавить во вторую коллекцию, а затем выпустите addAll метод в конце.
Использование ListIterator
Если вы работаете со списками, другой метод заключается в использовании ListIterator элемента, который поддерживает удаление и добавление элементов во время самой итерации.
Опять же, я использовал метод «удалить» в приведенном выше примере, что, по-видимому, подразумевает ваш вопрос, но вы также можете использовать его add метод для добавления новых элементов во время итерации.
Используя JDK> = 8
Для тех, кто работает с Java 8 или более поздними версиями, есть несколько других методов, которые вы можете использовать, чтобы воспользоваться этим.
Вы можете использовать новый removeIf метод в Collection базовом классе:
Или используйте новый потоковый API:
Использовать подсписок или подмножество
Есть и другие альтернативы. Если список отсортирован, и вы хотите удалить последовательные элементы, вы можете создать подсписок, а затем очистить его:
Поскольку подсписок поддерживается исходным списком, это будет эффективным способом удаления этого подколлекции элементов.
Нечто подобное может быть достигнуто с помощью сортированных наборов с использованием NavigableSet.subSet метода или любого из предложенных там методов нарезки.
Соображения:
Какой метод вы используете, может зависеть от того, что вы собираетесь делать
Как избежать java.утиль.ConcurrentModificationException при итерации и удалении элементов из ArrayList
какова наилучшая практика для решения этой проблемы? Должен ли я сначала клонировать список?
Я удаляю элементы не в самом цикле, а в другой части кода.
мой код выглядит так:
a.doSomething можно назвать Test.removeA() ;
15 ответов
в качестве примера второго варианта, удаление любых строк длиной более 5 из списка:
из JavaDocs ArrayList
итераторы, возвращаемые итератором и listIterator этого класса методы быстры: если список структурно изменен в любом случае время после создания итератора,в любом случае только через собственные методы удаления или добавления итератора, итератор бросит ConcurrentModificationException.
вы действительно должны просто повторить массив традиционным способом
каждый раз, когда вы удаляете элемент из списка, элементы после будут продвигаться вперед. Пока вы не изменяете элементы, отличные от итерационного, должен работать следующий код.
вы пытаетесь удалить значение из списка в расширенном «for loop», что невозможно, даже если вы применяете какой-либо трюк (который вы сделали в своем коде). Лучший способ-кодировать уровень итератора, как советуют здесь другие.
интересно, как люди не предложили традиционный для цикла подход.
но это будет означать ваш doSomething() должен быть в состоянии передать iterator до remove метод. Не очень хорошая идея.
затем, как только ваша итерация будет выполнена, просто сделайте removeAll из первого списка все элементы второго списка.
вот пример, где я использую другой список для добавления объектов для удаления, а затем использую stream.foreach для удаления элементов из списка :
в Java 8 Вы можете использовать интерфейс коллекции и сделать это, вызвав метод removeIf:
больше информации можно найти здесь
сделайте что-нибудь простое, как это:
вместо использования для каждого цикла используйте normal for loop. например, приведенный ниже код удаляет все элементы в списке массивов без указания java.утиль.ConcurrentModificationException. Вы можете изменить условие в цикле в соответствии с вашим вариантом использования.
» должен ли я сначала клонировать список?»
Это будет самое простое решение, удалить из Клона, и скопируйте клон после удаления.
пример из моей игры rummikub:
альтернативное решение Java 8 с использованием stream:
в Java 7 Вы можете использовать Guava вместо:
обратите внимание, что пример Guava приводит к неизменяемому списку, который может быть или не быть тем, что вы хотите.
при повторении списка, если вы хотите удалить элемент, это возможно. Давайте посмотрим ниже мои примеры,
Я выше имена список массива. И я хочу удалить имя » def » из приведенного выше списка,
приведенный выше код бросает ConcurrentModificationException исключение, потому что вы изменяете список во время итерации.
Итак, чтобы удалить имя » def » из Arraylist, сделав это путь,
вышеуказанный код, через итератор мы можем удалить имя » def » из Arraylist и попытаться распечатать массив, вы увидите ниже вывод.
Если ваша цель, чтобы удалить все элементы из списка, вы можете перебрать каждый элемент, а затем вызвать:
Я прибываю поздно, я знаю, но я отвечаю на это, потому что я думаю, что это решение простое и элегантное:
все это для обновления из одного списка в другой, и вы можете сделать все из одного списка и в методе обновления вы проверяете список и можете стирать или добавлять элементы между списком. Это означает, что оба списка всегда имеют одинаковый размер
Как удалить конкретный объект из ArrayList в Java?
Как удалить конкретный объект из ArrayList? Предположим у меня есть класс, как показано ниже:
как я могу удалить объект с new ArrayTest(1) от меня ArrayList
12 ответов
ArrayList удаляет объекты на основании equals(Object obj) метод. Поэтому вы должны правильно реализовать этот метод. Что-то вроде:
в общем случае объект может быть удален двумя способами из ArrayList (или вообще любой List ), по индексу ( remove(int) ) и объекта ( remove(Object) ).
в этом конкретном сценарии: добавьте equals(Object) метод ArrayTest класса. Что позволит ArrayList.remove(Object) определить правильный объект.
для удаления конкретного объекта из arrayList существует два способа. Вызовите функцию arrayList.
это удалит ваш объект, но в большинстве случаев, когда arrayList содержит элементы типов данных UserDefined, этот метод не дает вам правильного результата. Это работает только для примитивных типов данных. Поскольку пользователь хочет удалить элемент на основе значения поля объекта, и это может не сравнивайте функцией remove автоматически.
Если вы используете Java 8:
Java 8 имеет removeIf метод в интерфейсе коллекции. Для ArrayList он имеет расширенную реализацию (порядок n).
Авальчев прав. Более быстрым решением было бы проанализировать все элементы и сравнить по уникальному свойству.
это быстрое решение. Вам лучше реализовать сравнение объектов для более крупных проектов.
Как удалить элемент массива в Java?
В некоторых случаях возникает необходимость в удалении элементов из Java-массива. Однако язык программирования Java не предоставляет для выполнения этой операции прямого метода. Тем не менее ряд способов всё же имеется. О них и поговорим.
Начнём с того, что в обычном массиве удаление осуществляется не очень удобно. То есть мы не можем просто взять и удалить ячейку из Java-массива. Зато можем обнулить значение этой ячейки.
Итак, мы видим, что кот Вася благополучно обнулился. Однако при выполнении такой операции в Java-массиве остаётся «дыра», поскольку мы удаляем лишь содержимое ячейки, но не саму ячейку. То есть мы получаем пустую ячейку в середине массива, что не есть хорошо.
Что тут можно сделать? Например, переместить эту ячейку в самый конец массива, сдвинув другие элементы к началу:
Всё стало лучше, но, согласитесь, такое решение сложно назвать стабильным. Хотя бы потому, что каждый раз, когда нам надо будет удалить элемент из массива, нам придётся повторять вышеописанную операцию.
Использование ArrayList
Если гора не идёт к Магомету, Магомет идёт к горе. Если мы не можем удалить элемент в обычном массиве, мы можем преобразовать массив в структуру, позволяющую удалять элементы. А потом преобразовать эту структуру обратно в массив.
Выполнить вышеописанную схему нам поможет java.util.List или ArrayList. Дело в том, что в ArrayList реализован специальный метод, позволяющий удалять элементы — remove. В общем виде всё выглядит так:
Давайте теперь рассмотрим работу метода remove на наших котах:
Итак, мы передали в метод индекс нашего объекта, в результате чего он был удален.
Тут следует отметить следующие особенности метода remove() : — он не оставляет так называемых «дыр» — в нём реализована логика сдвига элементов, если мы удаляем элемент из середины. Вот вывод предыдущего кода:
То есть после удаления одного кота, остальные были передвинуты, и пробелов не осталось.
Кроме того, remove способен удалять объект не только по индексу, но и по ссылке:
Однако на просторах сети можно найти и другие способы удаления нужных элементов из массива.
Используем System.arraycopy
Мы можем просто создать копию исходного массива с помощью System.arraycopy(), удалив таким нехитрым способом соответствующий элемент:
Используем Apache Commons Lang
Последний способ, о котором стоит упомянуть, — применение библиотеки Apache Commons Lang и статического метода removeElement() класса ArrayUtils:
Apache Commons предоставляет нам библиотеку с именем org.apache.commons.lang3. Добавить библиотеку в ваш проект можно с помощью следующей maven-зависимости:
Данный пакет предоставляет класс ArrayUtils. Используя метод remove() этого класса, можно удалять элементы. Рассмотрим это на примере удаления повторяющихся элементов в массиве Java. Для обнаружения дублей надо сравнить каждый элемент Java-массива с оставшимися, для чего можно использовать 2 вложенных цикла.
Вот, как это будет работать:
На этом всё, надеемся, предоставленная информация была полезной!
Как удалить элемент из ArrayList, проверив его значение?
У меня есть ArrayList, из которого я хочу удалить элемент, который имеет определенное значение.
10 ответов
в вашем случае нет необходимости перебирать список, потому что вы знаете, какой объект удалить. У вас есть несколько вариантов. Сначала вы можете удалить объект по индексу (так что, если вы знаете, что объект является вторым элементом списка):
затем, вы можете удалить первый появление вашей строки:
или удалите все строки с определенным значением:
Это немного сложнее, если у вас есть более сложные объекты в вашей коллекции и хотите удалить экземпляры, которые имеют определенное свойство. Так что вы не можете удалить их с помощью remove С объектом, который равен тому, который вы хотите удалить.
в этом случае я обычно использую второй список, чтобы собрать все экземпляры, которые я хочу удалить, и удалить их во втором проходе:
(делает все итерации неявно)
вам нужно будет использовать итератор вот так:
Это, как говорится, вы можете использовать удалить (индекс int) или удалить (Object obj), которые предусмотрены ArrayList класса. Обратите внимание, однако, что вызов этих методов во время итерации по циклу вызовет ConcurrentModificationException, так что это не будет работать:
но это будет (так как вы не повторяете над содержимым цикла):
Если у вас есть более сложные объекты, вам нужно будет переопределить равна метод.