Как удалить элементы из HashMap без получения исключения ConcurrentModificationException - PullRequest
0 голосов
/ 01 февраля 2019

Я сравниваю каждую запись в HashMap с любой другой записью в том же HashMap.Во время итерации HashMap я удаляю некоторые элементы, основываясь на некоторых условиях.Однако я продолжаю получать ConcurrentModificationException.

    Iterator<Entry<String, String>> i = map.entrySet().iterator();

    while (i.hasNext()) {
        Entry<String, String> next = i.next();

        for (Entry<String,String> e : map.entrySet()) {

            if (e.getKey() != next.getKey()){                 
              String[] positions_e = fields_e[1].split("-");
              int start_e = Integer.parseInt(positions_e[0]);
              int end_e =  Integer.parseInt(positions_e[1]);

              String[] positions_next = fields_next[1].split("-");
              int start_next = Integer.parseInt(positions_next[0]);
              int end_next =  Integer.parseInt(positions_next[1]);

            if (start_e <= start_next || end_e <= end_next )) { 
                 i.remove();        
           } 

       }

   }

Ответы [ 5 ]

0 голосов
/ 01 февраля 2019

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

0 голосов
/ 01 февраля 2019

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

Извлеките ваше состояние с помощью отдельного метода:

private boolean myCondition(Entry<String, String> currentEntry, Map<String, String> map) {
    for (Entry<String, String> entry : map.entrySet()) {
        ...
        if (...) {
            return true;
        }

        return false;
    }
}

Используйте java8потоки для фильтрации карты в соответствии с вашими условиями:

Map<String, String> filteredMap = map.entrySet().stream()
    .filter(entry -> myCondition(entry, map))
    .collect(Collectors.toMap(Entry::getKey, Entry::getValue));
0 голосов
/ 01 февраля 2019

Используйте итератор или лямбду с removeIf для второго цикла.

for (Entry<String,String> e : map.entrySet())

Итератор для карты: https://www.techiedelight.com/iterate-map-in-java-using-entryset/

Лямбда для карты: https://javarevisited.blogspot.com/2017/08/how-to-remove-key-value-pairs-from-hashmap-java8-example.html#axzz5eHbDQxwp

0 голосов
/ 01 февраля 2019

Вы можете сохранить все keys в ArrayList и удалить любой ключ из HashMap, который хотите удалить, итерируя по ArrayList

public static void main(String[] args) {
    HashMap<String, Integer> map = new HashMap<>();

    map.put("1", 1);
    map.put("2", 2);
    map.put("3", 3);
    map.put("4", 4);
    map.put("5", 5);

    // store all the keys in an ArrayList
    ArrayList<String> keys = new ArrayList<>(map.keySet());

    for (String key : keys) {
        if (key.equals("2")) {
            map.remove(key); 
        }
    }
}
0 голосов
/ 01 февраля 2019

Вы удаляете элементы из коллекции с помощью итератора i, перебирая его с помощью другого итератора, неявного, используемого вашим циклом foreach.

У вас всегда будет эта проблемаесли вы вложили итерации в одну и ту же коллекцию и пытаетесь удалить элементы из внутреннего цикла.Использование внутреннего или внешнего итератора для удаления элемента из коллекции создает ConcurrentModificationException из другого итератора.

Поскольку вы используете i для удаления элемента, лучшая стратегия здесь, вероятно, заключается вbreak вне внутреннего цикла после вызова remove.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...