반응형

 자바에서 map이나 set에 특정한 원소들이 모두 있는지 확인하려면 어떻게 해야 할까요? stream을 생각하기 쉽지만, 사실 map이나 set에서는 containsAll을 쓰는 게 나을 수도 있습니다.

 


 

 containsAll은 collection이 c에 있는 모든 원소들을 가지고 있는지를 판단합니다. 보통 stream의 allMatch나, filter를 이용해서 처리하기도 할 텐데요. 저는 containsAll 메소드를 쓰는 것을 보다 선호합니다. 더 직관적이기 때문입니다. 사용법을 간단하게 보겠습니다. ori와 tar에 1부터 10까지 키를 넣었습니다.

 

 

 그러면 처음에 둘 다 1부터 10까지 들어있을 테니, ori가 tar에 있는 원소들을 모두 가지고 있는 것이 맞습니다. 문제는, ori에서 5를 제거했는데요. 그러면 ori에는 없는 5가 tar에는 있어요. 따라서 거짓이 되어 버립니다.

 

 

 결과는 요래 나옵니다.

 


 복잡도는 어떻게 될까요? c에 있는 모든 원소들에 대해서, collections에 해당 원소가 있는지를 탐색합니다. 즉, 어떠한 콜렉션에 콜렉션 c에 있는 모든 원소가 포함되는지 검사하는 containsAll은 어떠한 콜렉션의 contains 복잡도에 따라서 효율성이 결정됩니다. 일례로, 이런 경우에는 시간이 얼마나 걸릴까요?

 

 

 테스트 코드를 작성해 봅시다. ori와 tar는 arrayList입니다. 그리고, 저는 ori에서 Integer 10만을 제거하였습니다. 맨 끝의 원소를 제거한 것인데요. 이렇게 하면, containsAll 메서드는 리스트의 맨 끝에 가서야 10만이 없다고 판단하게 됩니다. 그러면 ori의 리스트 길이가 10만인데요. ArrayList의 contain 메소드. 정말 운이 안 좋으면 맨 끝까지 갈 거라는 불길한 예감이 듭니다.

 

 

 정말 그런지 확인해 보니, 그렇네요. A가 B에 있는 모든 원소들을 가지고 있는지 containsAll로 판단하는 작업은 A와 B가 무엇이냐에 따라 매우 비효율적으로 동작할 수 있습니다. 만약에 A가 list와 같이 어떠한 수 x가 있는지 판단하는 데 빠른 자료구조가 아니라면, 적당히 빠른 treeSet이나 hashSet 등으로 변경하시거나, 정렬 후 처리를 권해 드립니다.

 

 


 자바에서 map은 key와 value 쌍으로 이루어진 구조입니다. 저는 맵 ori가 맵 tar에 있는 키들을 모두 가지고 있는지 검사하고 싶습니다. 어떻게 하면 될까요? 맵에 있는 키들을 모두 가져오는 메서드는 keySet 메서드입니다.

 

 

 이 예제는 ori와 tar에 키를 1부터 10까지 넣고, 키 k에 대응되는 값을 k로 셋팅하였습니다. 12번째 줄을 보면, 1부터 10까지의 키가 ori에도 있고 tar에도 있으니, 1번째 결과는 참이 됩니다. 그런데, ori에서 5를 제거하였습니다. 5가 없는데, tar에는 5가 있으므로, 2번째 println 문에서는 false가 출력됩니다.

 

 

 정말 그렇게 출력이 되네요.

반응형

댓글을 달아 주세요