Не работает remove java

List, метод remove() баг в языке Java или миф? [закрыт]

Хотите улучшить этот вопрос? Обновите вопрос так, чтобы он вписывался в тематику Stack Overflow на русском.

Закрыт 2 года назад .

У нас 4 элемента:
Подсчёт по индексу: 0 1 2 3 (4 элемента)
А мне выдает ошибку:

Неправильно походу работает что ли?))

2 ответа 2

У вас был лист с индексами от 0 до 3. Вы удалили элемент( remove(1) ), их стало на 1 меньше, лист перестроился в лист с индексами от 0 до 2. После этого вы хотите удалить элемент с индексом 3( remove(3) ), а у вас уже нет такого индекса.

Напишите list.remove(2); и посмотрите, что выйдет. В ArrayList при вызове remove() ячейка удаляется из массива со смещением всех элементов к началу. Чтобы оставить по индексу пустое значение, нужно использовать list.set(2, null);

Всё ещё ищете ответ? Посмотрите другие вопросы с метками java list коллекции arraylist или задайте свой вопрос.

Похожие

дизайн сайта / логотип © 2021 Stack Exchange Inc; материалы пользователей предоставляются на условиях лицензии cc by-sa. rev 2021.10.18.40487

Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.

Источник

Удаление элемента списка в цикле foreach не бросает ConcurrentModificationException, почему?

Допустим, у меня есть некий ArrayList .

И я хочу из него удалить все числа больше 10.

«Правильно» сделать это можно через итератор, получив гарантированный результат.

Но на мое удивление, корректно работает и вариант:

Несмотря на то, что везде говорится, что любая попытка удаления из коллекции в цикле без использования итератора приводит к ConcurrentModificationException .

И, действительно, если будем удалять безусловно, получим как раз ConcurrentModificationException

Собственно, может кто-нибудь объяснить магию или дать наводку, где можно почитать на эту тему?

2 ответа 2

Видимо вам сказочно повезло:

  • у вас не было элементов, значение которых было больше 10
  • у вас был элемент, значение которого было больше 10, но он был только один и располагался на предпоследнем месте в списке

Давайте рассмотрим работу на более коротком примере.

Мы добавили три числа. Итак, как работает foreach

    Он получает итератор.

Проверяет на наличие следующего элемента hasNext() .

Если возвращается true , то берет следующий элемент с помощью next() .

Далее повторяются шаги 2 и 3 пока hasNext() не вернет false .

Если удалить элемент из списка, то его размер уменьшится и modCount увеличится.

Если удалить элемент во время итерации, то будет выброшено ConcurrentModificationException исключение на строке modCount != expectedModCount .

Но что происходит, если удаляется предпоследний элемент?

Когда мы удалим значение 22, то размер уменьшится до 2.

В других же случаях будет выброшено ConcurrentModificationException из-за modCount != expectedModCount .

А в этом единичном случае проверка пройдет на ура..

Источник

Реализовать метод add, remove и другие в своем списке

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Реализовать методы add и remove по индексу для самодельного списка
Есть самописный список, нужно реализовать функции add(value, index) и remove(index). Добавление и.

Groovy Метод remove на списке и на диапазоне
Здравствуйте, всем доброго времени суток . Q = println «Q = $Q» N = Q.remove(1) println «N.

Реализовать аппликативный оператор MY-REMOVE-IF с интерфейсом и семантикой, аналогично стандартному REMOVE-IF
Реализовать аппликативный оператор MY-REMOVE-IF с интерфейсом и семантикой, аналогично стандартному.

Решение

Ну у тебя же на схеме написано: #content: ConcurentLinkedDeque .

Реализация методов Add, Remove в классе ColectionBase
Добрый день, Изучаю С#, появился такой вопрос: Класс ColectionBase не содержит реализацию к.

Ошибка при явной реализации методов Add и Remove
Добрый день. Есть два класса событий MyEvent и MyEvent2, код ниже. С первым классов все в порядке.

Какой интерфейс идентичен ICollection но без методов Add(), Remove(), Clear()
Добрый вечер! Не подскажите интерфейс, который идентичен ICollection , за исключением того, что.

Как реализовать поиск в списке List, если отсутствует метод Find
Здравствуйте уважаемые форумчане, возникла очередная проблема. У меня есть public.

Источник

Удаление элементов из коллекций Java

Краткое руководство по удалению элементов из коллекции Java с использованием различных методов.

Автор: Daniel Barrigas
Дата записи

1. Обзор

В этом кратком руководстве мы поговорим о четырех различных способах удаления элементов из Java Коллекций , которые соответствуют определенным предикатам.

Естественно, мы также рассмотрим некоторые предостережения.

2. Определение Нашей Коллекции

Во-первых, мы проиллюстрируем два подхода, которые изменяют исходную структуру данных. Затем мы поговорим о двух других вариантах, которые вместо удаления элементов создадут копию оригинальной Коллекции без них.

Давайте используем следующую коллекцию в наших примерах, чтобы продемонстрировать, как мы можем достичь одного и того же результата, используя различные методы:

3. Удаление Элементов С Помощью Итератора

Java Итератор позволяет нам как ходить, так и удалять каждый отдельный элемент в пределах Коллекция .

Для этого нам сначала нужно получить итератор по его элементам с помощью метода iterator . После этого мы можем посетить каждый элемент с помощью next и удалить их с помощью remove :

Несмотря на его простоту, есть некоторые предостережения, которые мы должны учитывать:

  • В зависимости от коллекции, с которой мы можем столкнутьсяConcurrentModificationExceptionисключения
  • Нам нужно перебрать элементы, прежде чем мы сможем их удалить
  • В зависимости от коллекцииremoveможет вести себя иначе, чем ожидалось. Например: ArrayList.Итератор удаляет элемент из коллекции и сдвигает последующие данные влево, в то время как, LinkedList.Итератор просто настраивает указатель на следующий элемент. Таким образом, LinkedList.Итератор работает намного лучше, чем ArrayList.Итератор при удалении элементов

4. Java 8 и Collection.removeIf()

Java 8 представила новый метод для интерфейса Collection , который обеспечивает более краткий способ удаления элементов с помощью Предиката :

Важно отметить, что в отличие от подхода Iterator , removeIf одинаково хорошо работает как в LinkedList , так и в |/ArrayList .

В Java 8 ArrayList переопределяет реализацию по умолчанию, которая опирается на Итератор – и реализует другую стратегию: сначала он повторяет элементы и помечает те, которые соответствуют нашему предикату ; затем он повторяет второй раз, чтобы удалить (и сдвинуть) элементы, которые были отмечены в первой итерации.

5. Java 8 и введение потока

Одной из новых основных функций в Java 8 стало добавление Stream (и Collectors ). Существует множество способов создания потока из источника. Однако большинство операций, влияющих на экземпляр Stream , не изменяют его источник, скорее, API фокусируется на создании копий источника и выполнении любых операций, которые нам могут понадобиться в них.

Давайте посмотрим, как мы можем использовать Stream и Collectors для поиска/фильтрующих элементов, которые соответствуют и не соответствуют нашему Предикату .

5.1. Удаление Элементов С Потоком

Удаление, а точнее, фильтрующих элементов с помощью Stream довольно просто , нам просто нужно создать экземпляр Stream с помощью нашей Коллекции , вызвать фильтр с помощью нашего предиката , а затем собрать результат с помощью Коллекторов:

Потоковая передача менее инвазивна, чем предыдущие подходы, она способствует изоляции и позволяет создавать несколько копий из одного и того же источника. Однако мы должны иметь в виду, что это также увеличивает объем памяти, используемой нашим приложением.

5.2. Коллекторы.

Комбинирование Stream.filter и Collectors довольно удобно, хотя мы можем столкнуться со сценариями, в которых нам нужны как совпадающие, так и не совпадающие элементы. В таких случаях мы можем воспользоваться Collectors.partitioningBy :

Этот метод возвращает Map , который содержит только два ключа, true и false , каждый из которых указывает на список, содержащий соответствующие и несоответствующие элементы соответственно.

6. Заключение

В этой статье мы рассмотрели некоторые методы удаления элементов из Коллекций и некоторые из их предостережений.

Вы можете найти полный исходный код и все фрагменты кода для этой статьи на GitHub .

Источник

Коллекции в Java: о чём многие забывают

Из опыта code-review и ответов на StackOverflow набралось немало моментов, касающихся Java Collections API, которые мне казались очевидными, но другие разработчики о них почему-то не знали или знали, но не чувствовали уверенности их применять. В этой статье я собираю в общую кучу всё, что накопилось.

Содержание:

List.subList

Про это уже писали, но стоит повторить. Наверно, самый недооценённый метод из Collections API. Бывает, что надо каким-то образом обработать часть списка (например, в алгоритмах семейства «разделяй и властвуй» или при распараллеливании задачи). Многие создают метод или класс, который завязывается на три параметра: List, from и to:

Так незачем делать. Реализации алгоритма должно быть плевать, что она обрабатывает часть списка. Пишите:

Даже если у вас всё в одном методе, удобнее воспользоваться расширенным циклом for, чем возиться с индексами:

Кроме того, subList — полнофункциональный список, он работает и на запись, внося соответствующие изменения в родительский список. Нужно удалить много элементов из середины списка? Ничего нет проще:

У популярных реализаций вроде ArrayList это выполняется очень быстро.

Надо выяснить, начинается ли список с определённых элементов? И тут subList в руки!

Надо добавить в один список все элементы другого списка за исключением первого? И тут subList придёт на помощь:

Не забывайте, что можно писать Arrays.asList(array).subList(from, to) , поэтому вышесказанное применимо и для непримитивных массивов. Структурно менять вы их не сможете, но передавать кусок массива в метод, принимающий список для чтения — легко.

PriorityQueue

Если subList — самый недооценённый метод, то PriorityQueue — это, на мой взгляд, самый недооценённый класс. Многие сталкиваются с задачей отыскать, скажем, 10 минимальных значений большого несортированного списка. Чаще всего список сортируют и потом берут первые 10 значений. Если исходный список менять нельзя, придётся его ещё скопировать для сортировки. А ведь очередь с приоритетом легко справится с этой задачей:

Такой код в зависимости от данных может работать гораздо быстрее, чем сортировка. Например, для n = 10 и случайно заполненного списка из миллиона элементов очередь с приоритетом почти в сто раз обгоняет подход с сортировкой. При этом дополнительной памяти требуется O(n) и входные элементы можно обрабатывать в потоковом режиме (например, выбрать 10 наименьших чисел из входного файла).

Вообще людям свойственно изучить пару-тройку структур данных и пользоваться ими везде. Не ленитесь, познакомьтесь с разными структурами.

EnumSet и EnumMap

До сих пор встречается код, где значения типа enum используют в качестве ключей в HashSet и HashMap. Хотя это работает, но оно неоправданно расточительно. Существующие специальные классы EnumSet и EnumMap значительно производительнее. Так если в enum не больше 64 разных значений, EnumSet хранит всё в одном поле типа long в битовой маске. EnumMap содержит все значения в обычном массиве той же длины, сколько элементов в enum, а ключи не хранит вовсе. Так как у каждого значения в enum есть порядковый номер ordinal(), можно легко перейти от enum-ключа к элементу массива. Также никогда не нужно менять размер массива.

Set.add(E) и Set.remove(E) возвращают булево значение

Часто вижу подобный код:

Не надо забывать, что операция добавления в Set возвращает true, если добавление успешно (то есть элемента не было) и false, если такой элемент уже был. Незачем усложнять код и два раза пробивать элемент по хэш-таблице или двоичному дереву, ведь можно написать:

Аналогично с удалением. Цепочка if(set.contains(item)) < set.remove(item); . >заменяется на if(set.remove(item)) < . >.

Map.put(K, V), Map.remove(K), List.set(idx, E), List.remove(idx) возвращают предыдущий элемент

Из той же оперы ситуация. Методы, изменяющие или удаляющие элемент в коллекции возвращают предыдущее значение, и этим надо пользоваться. Не надо писать, например, так:

Написать просто Item item = myMap.put(key, newItem); . Хотите поменять местами две записи в Map с ключами key1, key2? Временная переменная не нужна:

Map.keySet() и Map.values()

Многие почему-то забывают, что Map.keySet() и Map.values() возвращают отображения исходного Map, которые позволяют удалять элементы (если Map модифицируемый). Надо оставить в Map только записи с определёнными значениями (и любыми ключами)? Пожалуйста:

Также работает removeAll , а с Java-8 ещё и removeIf :

Arrays.asList может быть ключом

Бывает, что вам нужно сформировать Map или Set, используя кортеж значений. Например, у вас есть PoJo-объекты Item , у которых имеются поля name, type, version . У них уже написан equals и hashCode , их можно складывать в HashSet , всё нормально. Но вы хотите выбрать из коллекции уникальные объекты только по полям name и type , игнорируя version. Менять существующие equals и hashCode нельзя. В таких ситуациях люди часто создают отдельный класс только с полями name и type и используют его в качестве ключа. Однако для одноразовой операции проще использовать Arrays.asList() :

Arrays.asList() создаёт список из нужного числа элементов и у него как раз подходящие реализации equals и hashCode : никакой boilerplate не нужен. Так можно создать ключ любой длины, причём корректно обработаются null-значения и примитивы (брагодаря боксингу). Не сработает только, если вы хотите в составе ключа иметь массив.

Collections.min/max

Удивительно, насколько часто можно встретить написанный вручную код, который находит максимальный или минимальный элемент чего-то по какому-нибудь критерию. Казалось бы, такая тривиальная задача должна быть давно решена. На самом деле она и так давно решена: есть методы Collections.min и Collections.max . Раньше было не очень удобно писать компараторы, но в Java-8 всё стало легче.

К примеру, вам нужно найти ключ в Map, соответствующий максимальному значению. Пишите так:

Можно и через Stream API, но Collections.max() несколько быстрее. Если вы не можете использовать Java-8 и компараторы вроде Entry.comparingByValue() вам недоступны, их нетрудно написать.

Stack, Vector, Hashtable, LinkedList

Просто не используйте эти классы. Пользы от них никакой нет. Вместо Stack пользуйтесь ArrayDeque, вместо Vector — ArrayList, вместо Hashtable — HashMap. Если вам нужна потокобезопасность, они вам всё равно не помогут. Возможно, в девятке их всё-таки пометят @Deprecated (смотрите JEP 277).

С LinkedList случай особый. Вроде бы лучшего аналога связного списка нет и ходят легенды, что он на самом деле полезен. В действительности ситуаций, когда LinkedList лучше, чем ArrayList, в реальной жизни исключительно мало. До Java-8 LinkedList ещё мог пригодиться, если вы часто удаляете элементы, идущие не последовательно, по какому-то условию. В Java-8 для этих целей появился List.removeIf , который в ArrayList, конечно, реализован оптимальнее (элементы передвигаются только один раз). Если вам надо сделать много вставок в разные места (задача сама по себе экзотическая), скорее всего быстрее будет создать новый ArrayList, чем вставлять в существующий LinkedList. Ну и помните, что LinkedList кушает в несколько раз больше памяти, так как каждый элемент — это отдельный объект в куче со ссылками на следующий и предыдущий. LinkedList можно использовать только в качестве учебного примера.

На сегодня всё. Программируйте с удовольствием!

Источник

Читайте также:  Как отремонтировать экрана планшета
Оцените статью