Map 계열 메서드 중에서 get, containsKey가 있습니다. 이들은 어떤 메소드들일까요?

 

 


 먼저, 다음과 같은 정보는 어디에선가 들어보셨으리라 생각이 듭니다. map 계열 구조에 Key값에 대응되는 값 Value를 불러오고 싶을 때 보통 이렇게 많이 쓴다.

 

프로그램 1

 그런데, 프로그램 1과 같이 작성하면, 불필요한 연산을 2번 하게 된다.

 

 

프로그램 2

 프로그램 2와 같이 쓰는 것이 좋다. 왜냐하면 불필요한 연산을 수행하지 않기 때문이다. 네. 이 부분은 맞습니다. containsKey나 get나 내부적으로 getNodes라는 것을 호출하는데요. 이것을 1번 수행하냐, 2번 수행하냐의 차이는 생각보다 크게 다가올 수 있습니다.

 

 여기서 질문 하나 드리겠습니다. 프로그램 1의 hm에 들어있는 key 값들의 집합을 k1이라고 하겠습니다. 프로그램 2의 hm에 들어있는 key 값들의 집합을 k2라고 하겠습니다. 프로그램 1의 K값은 k1에 속해있는 key 값 중에 임의의 값입니다. 프로그램 2의 K값은 k2에 속해있는 key 값 중에 임의의 값이라고 해 보겠습니다. 이 때, 두 프로그램은 항상 if문 조건이 참이 되어서, if문 안에 있는 문장을 수행할까요?

 

 

 get 메서드의 내부를 보겠습니다. getNode 메서드의 리턴 값이 null이면 null을 리턴합니다. 그렇지 않으면 e.value를 돌려줍니다. 

 

 

 반면에 containsKey는 getNode의 리턴 값이 null이 아니면 true를, 아니면 false를 리턴해 줍니다. 그러면 이 메서드는 어떻게 수행이 될까요? HashMap에서 어떻게 수행되는지 보겠습니다.

 

 

 중간에 있는 do while문만 봐도 알 수 있습니다. 중간에 key.equals(k)가 들어갔다는 것만 봐도, 어떤 값을 리턴하는지 알 수 있는데요. 이 상황을 그림으로 그려보겠습니다.

 

 

 만약에 Key가 k인 값을 Map 에서 찾는다고 한다면, Key값이 K인 객체를 리턴합니다. 만약에 없다면 null을 돌려줍니다. get 함수를 보면, Key값이 K인 객체가 있다면, 그것의 value 값을 돌려주는 처리를 또 다시 하고 있는데요.

 

 

 null value를 허용하는 구조라면, 어떨까요? key K값이 있어도 value 값이 null이라면, get(K)가 리턴하는 값은 null 입니다. 즉, 어떤 key K가 있는지 검사하고 싶다면, containsKey를 써야지, get(K)의 리턴값이 null이 아닌지 검사하면 안 된다는 것입니다. null value를 허용하는 경우가 있기 때문입니다. 널 값을 조심해야 한다는 겁니다.

 

 


 예제를 보겠습니다. HashMap에 <K,V>쌍 2개를 넣었습니다. 하나는 <5, null>, 다른 하나는 <3, 1>입니다.

 

 

  먼저, 10번째 줄을 보겠습니다. 2라는 키는 없습니다. 따라서 null이 출력될 겁니다. 이는 크게 문제 없습니다. 3이라는 키는 5라는 값과 쌍을 이루고 있기 때문에 5가 나옵니다. 여기까지는 별 문제가 없습니다. 그런데, h.get(5)가 문제입니다. 5라는 키가 있지만, null을 가지고 있기 때문에 널이 출력됩니다.

 

 이는 11번째 줄의 h.containsKey(5)와 대조적입니다. 5라는 키는 있기 때문에, 이것의 결과값은 true를 리턴합니다.

 

 

 당연하게도 결과는 이렇게 나오겠군요. 여담이지만, 프로그램 2가 성능상 더 빠를 수 있음에도, 저는 프로그램 1과 같이 많이 썼습니다. 그 이유는 제가 해당 기능을 코드를 작성했을 때 이해하기 더 쉬웠기 때문입니다.

 

 

 추가 질문. containsValue는 어떨까요? 이것도 많이 물어보는 것 중 하나입니다. Map 계열은 Key가 어디에 있는지를 빨리 찾기 위한 구조이지, Value가 맵 내에 어디에 있는지를 빨리 찾는 구조가 아닙니다.

 

 

 따라서 최악의 경우에 전체 데이터를 탐색해야 하고, 이 경우 복잡도는 O(자료구조에 들어있는 원소 갯수)만큼 됩니다.