10. HashMap

https://images.velog.io/images/tonyhan18/post/c4249991-7637-4381-b32b-e5320307b194/image.png

Map interface는 아래와 같이 구성된다. HashMap이라는 이름이 붙은 이유는 저장하는 방식이 Hashing이기 떄문이다. 그리고 탐색을 할때 빠른 속도를 보장한다.

HashMap의 class정의는 아래와 같이 구성이 된다.

public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable {
	transient Node<K,V>[] table;
	...

    // inner class가 따로 정의되어 있다.
    // Map.Entry를 구현한다. 여기에서 Key와 Value가 정의 된다.
    // 특이한 점은 key는 한 번 정의되면 바뀔 수가 없다.
	static class Node<K,V> implements Map.Entry<K,V> {
		final K key;
		V value;
		...
	}
}

HashMap: Methods

https://images.velog.io/images/tonyhan18/post/92a9eccb-6e2a-44e8-b1dd-49feff415276/image.png

HashMap의 정의 함수는 위와같이 구성된다.

https://images.velog.io/images/tonyhan18/post/a569ddaa-03f3-480a-b9d6-059dcdd21690/image.png

HashMap 내장 함수는 위와같이 구성된다.

여기에서 중요한 것은 어떻게 데이터를 가져오고 저장하는지이다. 그래서 getput 키워드가 존재하고 remove를 활용하여 데이터를 삭제한다. containsKeycontainsValue를 통하여 데이터의 키와 값을 찾을 수도 있다. 또 하나 특이한 것은 keySetvalues이다. 이것은 key또는 value를 모두 가져오는 것으로 반환형을 보면 keySet은 Unique한 Set을 사용하지만 values는 Collection을 사용하여 중복을 허용한다.

HashMap: Example 1

HashMap<String,String> map = new HashMap<>();
map.put("myId", "1234");
map.put("asdf", "1111");
map.put("asdf", "1234");
Scanner s = new Scanner(System.in);
while(true) {
	System.out.println("Please enter id and password.");
	System.out.print("id: ");
    //user의 입력을 받은 다음 뒤에 나오는 spacebar을 제거해 준다.
	String id = s.nextLine().trim();

	System.out.print("password: ");
	String password = s.nextLine().trim();
	System.out.println();

	if(!map.containsKey(id)) {
		System.out.println("id does not exist.");
		continue;
	} else {
		if(!(map.get(id)).equals(password)) {
		System.out.println("password does not match.");
	} else {
		System.out.println("welcome.");
		break; }
	}
}
s.close();

https://images.velog.io/images/tonyhan18/post/f15f6131-78b3-422a-a796-ee892eb31ee3/image.png

HashMap: Example 2

HashMap<String,Integer> map = new HashMap<>();
map.put("Kim Java", Integer.valueOf(90));
map.put("Kim Java", Integer.valueOf(100));
map.put("Lee Java", Integer.valueOf(100));
map.put("Kang Java", Integer.valueOf(80));
map.put("Ahn Java", Integer.valueOf(90));

Set<Map.Entry<String,Integer>> set = map.entrySet();
Iterator<Map.Entry<String,Integer>> it = set.iterator();
while(it.hasNext()) {
	Map.Entry<String,Integer> e = (Map.Entry<String,Integer>)it.next();
	System.out.println("name: " + e.getKey() + ", score: " + e.getValue());
}

Set<String> keys = map.keySet();
System.out.println("participants: " + keys);
Collection<Integer> values = map.values();
Iterator<Integer> it2 = values.iterator();
int total = 0;

while(it2.hasNext()) {
	Integer i = (Integer)it2.next();
	total += i.intValue();
}
System.out.println("total: " + total);
System.out.println("average: " + (float)total/set.size());
System.out.println("max: " + Collections.max(values));
System.out.println("min: " + Collections.min(values));

https://images.velog.io/images/tonyhan18/post/2270e712-fcbb-405b-a6f1-fd521b836b34/image.png

HashMap: Example 3

HashMap 안에 HashMap이 존재하는 경우

public class Lecture {
	static HashMap<String,HashMap<String,String>> phoneBook = new HashMap<>();

	public static void main(String[] args) {
		addPhoneNo("friend", "Lee Java", "010-111-1111");
		addPhoneNo("friend", "Kim Java", "010-222-2222");
		addPhoneNo("friend", "Kim Java", "010-333-3333");
		addPhoneNo("work", "Kim Daeri", "010-444-4444");
		addPhoneNo("work", "Kim Daeri", "010-555-5555");
		addPhoneNo("work", "Park Daeri", "010-666-6666");
		addPhoneNo("work", "Lee Guajang", "010-777-7777");
		addPhoneNo("laundary", "010-888-8888");
        // 들어가 있는 정보 모두 출력함
		printList();
	}

	static void addPhoneNo(String groupName, String name, String tel) {
		addGroup(groupName);
		HashMap<String,String> group = phoneBook.get(groupName);

		// 핸드폰 번호는 모두 다를 가능성이 이름에 비해 많기 때문에 전화번호를 key로 하고 value를 이름으로 작성했다.
        group.put(tel, name);
	}

    // 같은 groupName이 없다면 phoneBook에 삽입한다.
	static void addGroup(String groupName) {
		if(!phoneBook.containsKey(groupName)) phoneBook.put(groupName, new HashMap<String,String>());
	}

    // 매개변수가 2개인 경우의 삽입
	static void addPhoneNo(String name, String tel) {
		addPhoneNo("others", name, tel);
	}

    // printList를 통하여 모든 Entry를 출력한다.
	static void printList() {
		Set<Map.Entry<String,HashMap<String,String>>> set = phoneBook.entrySet();
		Iterator<Map.Entry<String,HashMap<String,String>>> it = set.iterator();

		while(it.hasNext()) {
        	//3개의 데이터를 가져온다.
			Map.Entry<String,HashMap<String,String>> e = (Map.Entry<String,HashMap<String,String>>)it.next();
            //가져온 데이터들을 또 작게 나눈다.
			Set<Map.Entry<String,String>> subset = e.getValue().entrySet();
			Iterator<Map.Entry<String,String>> subIt = subset.iterator();
			System.out.println(" * " + e.getKey() + "[" + subset.size() + "]");

			while(subIt.hasNext()) {
				Map.Entry<String,String> subE = (Map.Entry<String,String>)subIt.next();
				String telNo = subE.getKey();
				String name = subE.getValue();
				System.out.println(name + " " + telNo);
			}
			System.out.println();
		}
	}
}