[Java] HashSet 합집합 add(), addAll() 시 UnsupportedOperationException 날 경우
Java

[Java] HashSet 합집합 add(), addAll() 시 UnsupportedOperationException 날 경우

728x90

HashSet을 합치려고 시도하다가 UnsupportedOperationException 를 마주했다. 해결 후 기록으로 남겨두면 좋을 것 같아서 여기에 남긴다.

 

예를 들어 코드가 이런식이다.

 

코드:

Map<String, String> hashMap1 = new HashMap<>();
Map<String, String> hashMap2 = new HashMap<>();

Set<String> mySet1 = new HashSet<>();
Set<String> mySet2 = new HashSet<>();

hashMap1 = (맵1 불러오기 코드)
hashMap2 = (맵2 불러오기 코드)

mySet1 = hashMap1.keySet()
mySet2 = hashMap2.keySet()

mySet1.addAll(mySet2); // 오류 

오류메시지:

java.lang.UnsupportedOperationException
    java.util.AbstractList.add(Unknown Source)
    java.util.AbstractList.add(Unknown Source)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)

 

일반적으로 HashSet 두 개를 합칠때 addAll() 을 사용한다.

 

그렇다면 왜 이런 에러가 날까?

자바 도큐멘테이션중 HashMap#keySet() 을 보면 이유를 알 수 있다.

 

Returns a Set view of the keys contained in this map. The set is backed by the map, so changes to the map are reflected in the set, and viceversa. If the map is modified while an iteration over the set is in progress (except through the iterator's own remove operation), the results of the iteration are undefined. The set supports element removal, which removes the corresponding mapping from the map, via the Iterator.remove, Set.remove, removeAll, retainAll, and clear operations. It does not support the add or addAll operations.

 

요약 (한글):

mySet1 = hashMap1.keySet() 이런식으로 Set에 Map의 Key를 지정해놓는다면, 서로의 변화의 영향을 준다. (예: hashMap1에 새로운 Key가 추가된다면 mySet1에 변화가 생기고, mySet1에 새로운 element가 추가되면 hashMap1에 새로운 Key가 생긴다). 만약 Set에서 iteration이 일어나는동안 연결된 Map에 변화가 생기면 iteration결과가 undefined가 된다. 

따라서 .keySet()으로 Set와 Map을 연결시켜주는 경우에는 remove, removeAll, retainAll, clear 함수는 사용이 가능하지만 add, addAll은 사용이 불가하다

 

 

해결방법:

하지만 우리는 방법을 찾을 것이다. 늘 그래왔듯이...

해당 오류를 bypass하는 방법은 아주 간단하다.

새로운 Set을 만들어서 그안에 두 Set (keySet으로 지정된)를 addAll 해주면 된다. 예시는 아래와 같다

 

Map<String, String> hashMap1 = new HashMap<>();
Map<String, String> hashMap2 = new HashMap<>();

Set<String> mySet1 = new HashSet<>();
Set<String> mySet2 = new HashSet<>();

hashMap1 = (맵1 불러오기 코드)
hashMap2 = (맵2 불러오기 코드)

mySet1 = hashMap1.keySet()
mySet2 = hashMap2.keySet()

//mySet1.addAll(mySet2); // 오류 

Set<String> totalSet = newHashSet<>();
totalSet.addAll(mySet1);
totalSet.addAll(mySet2);

 

오늘도 새로운 걸 배운다.

728x90

'Java' 카테고리의 다른 글

[Java] JVM 동작 및 실행 과정  (0) 2022.09.28
[Java] JVM, JRE, JDK?  (0) 2022.09.28
[Java] 자바(Java)의 역사  (0) 2022.09.27
[Java] JSON 파싱하기 (jackson/gson/json-simple)  (1) 2021.10.16
[Java] 자바 Null 체크, 빈 값("") 체크  (0) 2021.06.16