※전체코드는 맨 아래 있습니다.
자바에서 map을 직접 반복하는 방법은 없고 map에서 제공해주는 set을 통해 반복해야 한다.
set을 반복하는 방법은 단순 for문과 iterator를 이용한 방법, 총 2가지가 있다.
map에서 제공하는 set은 2종류다. keySet과 entrySet
그러므로 map을 반복하는 방법은 keySet반복개수(2) + entrySet반복개수(2)로 총 4개의 방법이 있다.
예시로 다음과 같은 map을 가지고 하겠다.
Map<String,String> map=new HashMap<>();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
그러면 map에는 다음과 같은 형태로 값이 저장 될 것이다.
key | value |
key1 | value1 |
key2 | value2 |
key3 | value3 |
1.keySet
map에서 제공해주는 keySet() 메소드를 통해 key에 관한 Set을 얻을 수 있다.
이 예제에서는 ["key1","key2", "key3" ] 이라는 Set을 얻게 된다.
이 Set을 통해 for문과 iterator 원하는 반복형태로 반복하면 map을 반복 할 수 있다.
Set<String> keySet = map.keySet(); //[key1, key2, key3]
//set에서 직접 for문
for (String key : keySet) { //key는 key1, key2, key3이 반복 될거고 각각의 key값을 통해 map에서 각각의 value값을 얻을 수 있다.
String value = map.get(key);
System.out.print("key값 = " + key + ", \t");
System.out.println("value값 = " + value);
}
System.out.println();
//set에서 iterator 얻은 후 iterator 반복
Iterator<String> iterator = keySet.iterator();
while (iterator.hasNext()) {
String key = iterator.next();
String value = map.get(key);
System.out.print("key값 = " + key + ", \t");
System.out.println("value값 = " + value);
}
2.EntrySet
map에서 제공해주는 entrySet() 메소드를 통해 Entry에 관한 Set을 얻을 수 있다.
근데 여기서 의문은 keySet은 String 타입의 key를 Set형태로 제공한다고 했다.
그래서 keySet의 데이터 타입은 Set<String> 이었다.
Set<String> keySet = map.keySet(); //[key1, key2, key3]
마찬가지로 entrySet의 데이터 타입은 Set<Entry> 일 것이다.
그럼 Entry란 무엇일까?
Entry란 key와 value로 이루어진 하나의 데이터 형태이다.
이렇게 (key,value)로 이루어진 걸 Entry라고 하고 이 Entry가 모여서 만들어진게 Map이다.
Entry는 Map 내부의 Interface로 정의 되어있고,
우리가 실제로 만든 HashMap에서는 이 Entry를 상속 받은 Node가 정의 되어있다.
public interface Map<K,V> {
interface Entry<K,V> {
/**
* Returns the key corresponding to this entry.
*
* @return the key corresponding to this entry
* @throws IllegalStateException implementations may, but are not
* required to, throw this exception if the entry has been
* removed from the backing map.
*/
K getKey();
/**
* Returns the value corresponding to this entry. If the mapping
* has been removed from the backing map (by the iterator's
* <tt>remove</tt> operation), the results of this call are undefined.
*
* @return the value corresponding to this entry
* @throws IllegalStateException implementations may, but are not
* required to, throw this exception if the entry has been
* removed from the backing map.
*/
V getValue();
.....
}
}
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable {
.....
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
...
}
...
}
Entry는 제네릭으로 만들어지기 때문에 데이터 타입은 Entry<K,V>이다.
예제에서는 Map을 만들 때
Map<String, String> map = new HashMap<>();
으로 만들었기 때문에 Entry<String,String>이 된다.
이 때 Entry자체는 Map의 내부 인터페이스이기 때문에 entrySet() 메소의 return 타입은 다음과 같다.
Set<Map.Entry<String, String>> entrySet = map.entrySet();
만약 java.util.Map.Entry를 import 한다면 다음과 같이 된다. ( import java.util.Map.Entry; )
Set<Entry<String, String>> entrySet = map.entrySet();
이제 이 entrySet을 가지고 for문이나 iterator를 통해 반복해주면 된다.
// Set<Map.Entry<String, String>> entrySet = map.entrySet(); //Map.entry import하기 전
Set<Entry<String, String>> entrySet = map.entrySet();
//set에서 직접 for문
for(Entry<String,String> entry : entrySet){
String key=entry.getKey();
String value=entry.getValue();
System.out.print("key값 = " + key + ", \t");
System.out.println("value값 = " + value);
}
System.out.println();
//iteraotr얻어서 반복
Iterator<Entry<String,String>> entryIterator= entrySet.iterator();
while (entryIterator.hasNext()){
Entry<String,String> entry=entryIterator.next();
String key=entry.getKey();
String value=entry.getValue();
System.out.print("key값 = " + key + ", \t");
System.out.println("value값 = " + value);
}
이렇게 총 4가지의 map반복에 대해 알아보았다.
map반복에서 중요한 건 map에서 Set을 얻은 다음 Set을 반복한다는 것이다.
나는 처음에 map 반복 할 때 마다 인터넷을 참고했었는데 set을 반복한다는 것을 알고나서는
안 보고 자연스럽게 하게 되었다. 여러분들도 Map 반복을 안 보고 자연스럽게 할 수 있으면 좋겠다.
마지막으로 전체 코드이다.
import java.util.*;
import java.util.Map.Entry;
public class Main {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
Set<String> keySet = map.keySet(); //[key1, key2, key3]
//set에서 직접 for문
for (String key : keySet) { //key는 key1, key2, key3이 반복 될거고 각각의 key값을 통해 map에서 각각의 value값을 얻을 수 있다.
String value = map.get(key);
System.out.print("key값 = " + key + ", \t");
System.out.println("value값 = " + value);
}
System.out.println();
//set에서 iterator 얻은 후 iterator 반복
Iterator<String> iterator = keySet.iterator();
while (iterator.hasNext()) {
String key = iterator.next();
String value = map.get(key);
System.out.print("key값 = " + key + ", \t");
System.out.println("value값 = " + value);
}
System.out.println();
System.out.println();
// Set<Map.Entry<String, String>> entrySet = map.entrySet(); //Map.entry import하기 전
Set<Entry<String, String>> entrySet = map.entrySet();
//set에서 직접 for문
for(Entry<String,String> entry : entrySet){
String key=entry.getKey();
String value=entry.getValue();
System.out.print("key값 = " + key + ", \t");
System.out.println("value값 = " + value);
}
System.out.println();
//iteraotr얻어서 반복
Iterator<Entry<String,String>> entryIterator= entrySet.iterator();
while (entryIterator.hasNext()){
Entry<String,String> entry=entryIterator.next();
String key=entry.getKey();
String value=entry.getValue();
System.out.print("key값 = " + key + ", \t");
System.out.println("value값 = " + value);
}
}
}
※ 위의 4가지 방법말고 forEach메소드를 이용해서 할 수도 있지만, entrySet iterator와 똑같은 방식이다.
map.forEach( (key, value) -> {
System.out.print("key값 = " + key + ", \t");
System.out.println("value값 = " + value);
});
또 set에서 stream을 이용해서 반복 할 수도 있다.