이번에 배울 Map은 앞에서 배운 List와 Set 과는 조금 다릅니다. 일단 Map 만큼은 Collection 인터페이스를 상속받지 않습니다. 당연히 사용하는 메서드도 이들과는 다르겠죠?(추상화)
Map과 List를 한번 비교해 보도록 하겠습니다. Map 은 List처럼 인덱스를 가지고 있습니다. 하지만 인덱스는 숫자가 아니라 문자입니다.
이 문자 인덱스를 “키”라고 부릅니다. 그리고 List는 값을 넣으면 자동으로 인덱스가 부여되지만 Map 은 키와 값 둘 다 넣어 줘야만 합니다.
이때 List는 우리가 이미 알듯이 값의 중복을 신경 쓰지 않습니다. Map 역시도 값의 중복은 신경 쓰지 않습니다만 키가 중복될 경우 이전 키의 값을 덮어쓰게 됩니다. 사실, List 도 인덱스가 중복된다면 해당 인덱스의 값을 덮어쓰긴 하죠.
그리고 Map 은 순서가 없습니다. 엄밀히 말하면 있긴 있지만, 경우에 따라 순서가 뒤바뀌기도 하기 때문에 ‘없다’라고 생각하는 것이 좋습니다.
사실 Map의 키는 입력된 키를 Hash라는 16진수 값으로 바꿔서 저장하기에 이 16진수 숫자의 순서로 정렬합니다. 하지만 이 Hash 값이 우리가 일반적으로 생각하는 정렬순서가 아닐 수도 있기에 순서가 없다고 표현하는 것입니다.
* 혹시 해쉬에 대해 궁금하다면?(블록체인과 비트코인)
일반적으로 Map 은 List처럼 특정한 인덱스(키)를 부르면 해당하는 값이 나오게 됩니다. List처럼 검색이 가능한 것이죠.
그런데 말이죠? 만약 List와 Set, Map의 모든 값을 모두 뽑아보고 싶다면 어떻게 해야 할까요?
List는 인덱스라는 숫자가 있으므로 0부터 시작해서 1씩 증가해 가면서 값을 불러낼 수 있습니다.
Set 은 Iterator 형태로 변경한 다음 하나씩 꺼낼 수 있습니다.
마지막으로 Map 은요?
Map 은 Key와 Value를 가지고 있어 이 내용을 어떻게 분리하는지에 따라서 꺼내는 방법이 달라집니다.
키만 따로 분류해 낼지, 키와 값을 한쌍으로 가지고 있는 Entry 기준으로 분리해 낼지 선택해야 합니다.
물론 우리는 두 가지 방법을 다 알아볼 생각입니다.
키만 따로 분리해 내는 방법을 먼저 알아보겠습니다.
먼저 키만 따로 분리하여 Set으로 저장을 합니다. 이것을 Key Set이라고 부릅니다. 그리고 Set을 하나씩 뽑아내기 위해서는 Iterator 형태로 변환을 해야 하죠? 그다음 각각 꺼내진 키를 이용하여 해당하는 값을 불러 냅니다. 이렇게 하면 Map 안의 모든 키를 꺼내 해당하는 값까지 알아낼 수가 있습니다.
그럼 Entry를 분리하는 방식은 어떨까요?
우선 키와 값이 한 쌍인 Entry를 분리하여 Set의 형태로 저장합니다. 그리고 이들을 하나씩 뽑아낼 수 있도록 Iterator 화 시켜줍니다. 그리고 꺼내 온 Entry에서 각각의 키와 값을 불러옵니다.
어떤 것이 더 좋은 방법이다라는 것은 없습니다. 그저 여러분들이 상황에 맞게 어떤 방법을 취하느냐 만 있을 뿐이죠!
Map 역시도 Map 인터페이스를 구현받는 클래스들로 이루어져 있습니다. 그중 가장 자주 쓰이는 것은 HashMap입니다. Properties라는 것도 의미는 있지만 파일이 엮여 있기 때문에 이번엔 다루지 않을 생각입니다. HashTable 과의 비교만 해보도록 하겠습니다.
List에서 본 적이 있죠? 바로 List와 Vector의 관계, 그리고 앞에서 배운 StringBuilder와 StringBuffer의 관계와 같습니다. 모든 것이 같지만 동기화의 지원 여부만 다릅니다!