Java - 반복문 안에서 HashMap 요소 삭제

for, while 등, 반복문 안에서 HashMap을 순회하면서 요소를 삭제하는 방법을 소개합니다.

1. ConcurrentModificationException

반복문을 이용하여 HashMap을 순회하면서 특정 조건의 요소를 삭제하는 경우가 있습니다.

문제는 HashMap 순회 중, 요소를 삭제하면 ConcurrentModificationException가 발생할 수 있습니다.

예를 들어, 아래 처럼 HashMap을 순회하면서 HashMap.remove()로 요소를 삭제하면 Exception이 발생할 수 있습니다. 따라서, 아래와 같은 방식으로 삭제하면 안됩니다.

import java.util.HashMap;

public class Example {

    public static void main(String[] args) {

        HashMap<String, Integer> map = new HashMap<>();
        map.put("apple", 100);
        map.put("kiwi", 200);
        map.put("banana", 300);
        map.put("grape", 400);

        for (String key: map.keySet()) {
            if (key.startsWith("k")) {
                map.remove(key);
            }
        }

        System.out.println(map);
    }
}

Output:

Exception in thread "main" java.util.ConcurrentModificationException
	at java.base/java.util.HashMap$HashIterator.nextNode(HashMap.java:1597)
	at java.base/java.util.HashMap$KeyIterator.next(HashMap.java:1620)
	at Example.main(Example.java:13)

2. Iterator로 순회 중 요소 삭제

Iterator를 이용하여 순회하면서 Iterator.remove()로 요소를 삭제하는 것은 Exception이 발생하지 않습니다.

아래와 같이 특정 요소를 삭제하도록 구현할 수 있습니다.

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class Example {

    public static void main(String[] args) {

        HashMap<String, Integer> map = new HashMap<>();
        map.put("apple", 100);
        map.put("kiwi", 200);
        map.put("banana", 300);
        map.put("grape", 400);

        Iterator<Map.Entry<String, Integer>> it = map.entrySet().iterator();
        while (it.hasNext()) {
            if (it.next().getKey().startsWith("k")){
                it.remove();
            }
        }

        System.out.println(map);
    }
}

Output:

{banana=300, apple=100, grape=400}

3. List를 이용하여 HashMap 요소 삭제

HashMap 순회 중 삭제할 요소를 리스트에 저장하고, List를 다시 순회하면서 HashMap의 요소를 삭제할 수 있습니다. HashMap 순회 중 요소를 삭제하는 것이 아니기 때문에 ConcurrentModificationException이 발생하지 않습니다.

아래와 같이 요소 삭제를 할 수 있습니다.

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class Example {

    public static void main(String[] args) {

        HashMap<String, Integer> map = new HashMap<>();
        map.put("apple", 100);
        map.put("kiwi", 200);
        map.put("banana", 300);
        map.put("grape", 400);

        List<String> willRemove = new ArrayList<>();
        for (String key: map.keySet()) {
            if (key.startsWith("k")) {
                willRemove.add(key);
            }
        }

        for (String str : willRemove) {
            map.remove(str);
        }
        System.out.println(map);
    }
}

Output:

{banana=300, apple=100, grape=400}

4. removeIf()로 순회 중 요소 삭제

removeIf()는 인자로 인자 1개와 리턴 값이 있는 함수형 인터페이스를 받습니다. 이 함수에서 어떤 요소에 대해서 true를 리턴하면, 그 요소는 삭제됩니다.

removeIf()도 ConcurrentModificationException을 발생시키지 않기 때문에, 이 방법으로 요소를 삭제할 수 있습니다.

아래와 같이 특정 요소를 삭제하도록 구현할 수 있습니다.

import java.util.HashMap;

public class Example {

    public static void main(String[] args) {

        HashMap<String, Integer> map = new HashMap<>();
        map.put("apple", 100);
        map.put("kiwi", 200);
        map.put("banana", 300);
        map.put("grape", 400);

        map.entrySet().removeIf(entry -> entry.getKey().startsWith("k"));

        System.out.println(map);
    }
}

Output:

{banana=300, apple=100, grape=400}

4.1 HashMap.keySet().removeIf()

entrySet() 대신에 keySet()을 사용하여 요소를 삭제할 수도 있습니다.

keySet()은 HashMap의 모든 key에 대한 collection이기 때문에, key만 순회할 수 있습니다.

import java.util.HashMap;

public class Example {

    public static void main(String[] args) {

        HashMap<String, Integer> map = new HashMap<>();
        map.put("apple", 100);
        map.put("kiwi", 200);
        map.put("banana", 300);
        map.put("grape", 400);

        map.keySet().removeIf(key -> key.startsWith("k"));

        System.out.println(map);
    }
}

Output:

{banana=300, apple=100, grape=400}

4.2 HashMap.values().removeIf()

values()는 HashMap의 value들을 collection으로 리턴하며, removeIf()로 특정 value에 대한 요소를 삭제할 수 있습니다.

import java.util.HashMap;

public class Example {

    public static void main(String[] args) {

        HashMap<String, Integer> map = new HashMap<>();
        map.put("apple", 100);
        map.put("kiwi", 200);
        map.put("banana", 300);
        map.put("grape", 400);

        map.values().removeIf(val -> val == 200);

        System.out.println(map);
    }
}

Output:

{banana=300, apple=100, grape=400}
Loading script...
codechachaCopyright ©2019 codechacha