본문 바로가기
Java/CollectionFramework

Collection framework - Map

by GGShin 2022. 5. 15.

Collection framework에는 Collection interface와 Map interface가 있습니다. 이번에는 그 중 Map interface에 대해서 알아보겠습니다. 

Map interfaced의 가장 큰 특징은 key와 value의 쌍으로 되어있다는 것입니다. Swift의 dictionary와 유사하더라구요. 

Key & value pair는 entry라고 부릅니다.

shorturl.at/dnpz1

Swift에서와 마찬가지로 Java의 Map 역시 순서가 정리되지 않더라구요. 그래서 Array와는 다르게 index를 이용하지 않고 key를 사용합니다. 예를 들어 Map 안에 요소들을 찾을 때도 index 대신 key를 사용하면 됩니다. 그렇기 때문에 key는 중복된 key가 들어가면 안됩다. key로 요소들을 관리하는데 동일한 key가 있으면 정확한 요소를 가지고 올 수 없으니까 그렇겠죠? 

만약에 이미 사용되고 있는 key를 이용해 value를 넣게 되면, 새로운 value로 덮어씌워지게 됩니다. 

한 번 어떻게 Map을 사용할 수 있는지 알아보겠습니다.

위의 도표에 나온 것처럼 Map interface를 implements하는 class는 3가지가 있는데요,

 

Hashmap           LinkedHashMap            TreeMap

 

그래서 Map을 사용하겠다 하면 이 셋 중에서 사용해주면 됩니다. 셋 다 Map interface를 implements하고 있으므로 선언부에 Map으로 표시해주어도 무방합니다.  

Map<String, String> myMap1 = new HashMap<>();

Map<String, String> myMap2 = new LinkedHashMap<>();

Map<String, String> myMap3 = new TreeMap<>();

 

그리고 <> 다이아몬드 안에는 key와 value의 타입을 명시해주면 됩니다. Key, value 이렇게 두개가 사용이 되므로 타입도 두개 명시해주는 겁니다.

 

1. Key, value 추가하기

요소를 추가하려면, .put(key, value)를 사용하면 됩니다.

 Map<String, String> languages = new HashMap<>();
 languages.put("Java", "a compiled high level, object-oriented language");

 

위에서 말한 것 처럼 중복된 key를 사용해서 value를 또 추가하게되면 새로운 value로 덮어씌워집니다.

 

 Map<String, String> languages = new HashMap<>();
 languages.put("Java", "a compiled high level, object-oriented language");
 
 languages.get("Java");
 //Prints "a compiled high level, object-oriented language"
 
 //Java key에 새로운 value 추가
 languages.put("Java", "overwrting on Java");
 languages.get("Java");
 //Prints "overwrting on Java"

 

.put()과 System.out.print()를 같이 사용해서 이미 사용되고 있는 key인지 확인해볼 수도 있습니다.

 

languages.put("Java", "a compiled high level, object-orient");

//Python key는 이전에 추가된 적이 없었기 때문에 line#3에서 null이 프린트됩니다.
System.out.println(languages.put("Python", "an interpreted, object-oriented, "));

//Java key는 line#1에서 이미 추가된 적이 있었기 때문에 line#5에서 기존의 value인
//"a compiled high level, object-orient"이 프린트됩니다.
System.out.println(languages.put("Java", "overwriting on Java"));

기존에 한번도 사용되지 않았던 key는 .put() 사용 시에 null을 반환합니다. 사용되고 있던 key라면 기존에 저장되어 있던 value를 반환합니다.

 

그렇지만 이 방법은 어찌되었든 기존 key에 value가 덮어씌워지는 것을 막지는 못합니다. 

대신 .containsKey(key)를 사용하면 boolean을 반환 받으며 key가 존재하는지만 확인할 수도 있습니다. (이미 있는 key이면 true, 없는 key이면 false 반환)

 

if(languages.containsKey("Java")) {

    System.out.println("Java is already used");
    
} else {

    languages.put("Java", "Hi it's me Java!");
    
} //Prints "Java is already used"

 

위와 같이 특정 key가 사용되고 있는지 여부에 따라 다른 행동이 되도록 설정할 수 있습니다.

예시에서는 이미 Java key가 사용되고 있으므로 위 예시에서는 "Java is already used" 가 프린트 되고, 새로운 value로 덮어 씌워지지 않게 됩니다.

 

2. Value 가져오기

value를 가져오려면 .get(key)를 사용하면 됩니다.

 

 languages.put("Java", "overwrting on Java");
 languages.get("Java");
 //Prints "overwrting on Java"

 

위에서 사용했던 코드 중에도 .get()으로 값을 불러온 코드가 있었습니다.

Array에서 for loop을 사용하여 하나씩 요소들을 프린트 하는 것을 Map에서도 할 수 있습니다. 바로 .keySet()을 사용하면 되는데요, .keySet()을 사용하면 해당 map에 들어있는 key들의 Set을 반환받습니다. (value는 제외)

 

for(String key : languages.keySet()) {
	System.out.println(key + " : " + languages.get(key));
}

//Prints
//Java : overwriting on Java
//BASIC : Beginners All Purposes Symbolic Instruction Code
//Lisp : Therein lies madness
//Python : an interpreted, object-oriented, 
//Algol : an algorithmic language
//위의 프린트 순서는 매번 수행 시마다 변동될 수 있습니다. 
//Map은 순서를 상관하지 않고 저장하기 때문입니다!

 

Key와 value pair를 Set형태로 반환받고 싶다면 .entrySet() method를 사용하면 됩니다. 

 

//Set 변수 entrySet 만들어서 데이터 할당
Set<Map.Entry<String,String>> entrySet = languages.entrySet();
//Map에는 iterator()가 없지만 Set은 있으므로 Set을 이용해서 iterator 사용
Iterator<Map.Entry<String,String>> entryIterator = entrySet.iterator();

while(entryIterator.hasNext()) {
  Map.Entry<String,String> entry = entryIterator.next();
  String key = entry.getKey();
  String value = entry.getValue();
  System.out.println("Key: " + key + " Value: " + value);
}

 

 

 

3. Key, value 삭제하기

 

요소를 삭제할 때는 .remove(key) 또는 .remove(key, value)를 사용하면 됩니다.

 

//Python key 삭제 (value도 같이 삭제)
languages.remove("Python");
        
for(String key : languages.keySet()) {
    System.out.println(key + " : " + languages.get(key));
}

Python key를 삭제하고 난 후에 key와 value를 프린트해보면 

Python key & value만 잘 삭제된 것을 확인할 수 있습니다.

 

Key뿐만 아니라 value도 parameter로 넣어서 확인한 후에 삭제할 수도 있습니다.

languages.remove("Python", "an interpreted, object-oriented");

 

이렇게 하면 key 뿐만 아니라 value도 정확해야 삭제가 가능하게 됩니다.

 

4. value 값 바꾸기 

 

이미 map에 포함되어 있는 key인 경우 .replace(key, value) 를 사용하면 됩니다. 이때 value 부분에는 새롭게 바뀔 value를 넣어주면 됩니다. 또는 .replace(key, old value, new value)를 사용할 수도 있습니다.

 

languages.replace("Java","Hello Java");
System.out.println(languages.get("Java"));
//Prints "Hello Java"

 

.replace() 도 .remove() 처럼 기존 value까지 넣어서 확인한 후에 replace가 되게 할 수 있습니다.

 

languages.replace("Java","overwriting on Java", "Hello Java");
System.out.println(languages.get("Java"));
//Prints "Hello Java"

.put을 사용한 덮어씌우기와는 다른 점은, .replace()는 기존에 key가 있는 경우에만 동작한다는 것입니다.

Map내에 해당 key가 없는 경우라면 .replace()를 했을 때 아무 일도 일어나지 않습니다!

 

만약에 langues.replace() 이 코드를 System.out.print()를 해보면 어떻게 될까요? 

.put() 때와 마찬가지로 이전의 값을 반환해줍니다.

 

System.out.println(languages.replace("Java", "Hello Java"));
//Prints "overwriting on Java"

만약에 없는 key라면 null을 반환합니다. 

 

그런데, .replace(key, old value, new value)를 사용할 경우에는 정상적으로 변경되는 경우에는 true를, 변경이 이루어지지 않은 경우에는 false를 반환합니다.

 

이렇게 Map interface를 사용하는 방법을 hash map을 통해서 알아보았습니다. 

Map을 implements 하는 다른 도구들도 다음번에는 알아보도록 하겠습니다. 

감사합니다. ☺️ 

반응형

'Java > CollectionFramework' 카테고리의 다른 글

LinkedList 사용하기  (2) 2022.05.22
ArrayList  (0) 2022.05.03