본문
HashMap(JAVA)
# HashMap
HashMap은 키(key)와 값(value)을 묶어서 하나의 데이터(entry)로 저장한다는 특징을 갖는다.
그리고 해싱(hashing)을 사용하기 때문에 많은 양의 데이터를 검색하는데 있어서 뛰어난 성능을 보인다.
비객체지향적인 코드 |
객체지향적인 코드 |
Object[] key; Object[] value; |
Entry[] table; class Entry { Object key; Object value; } |
- 키(key) : 컬렉션 내의키(key) 중에서 유일해야 한다.
- 값(value) : 키(key)와 달리 데이터의 중복을 허용한다.
키는 저장된 값을 찾는데 사용되는 것이기 때문에 컬렉션 내에서 유일해야한다.
즉, HashMap에 저장된 데이터를 하나의 키로 검색했을 때 결과가 단 하나이어야 함을 뜻한다.
만일 하나의 키에 대해 여러 검색결과 값을 얻는다면 원하는 값이 어떤 것인지 알 수 없기 때문이다.
Source 01) HashMapEx01.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | package hashMapEx; import java.util.HashMap; import java.util.Scanner; public class HashMapEx01 { public static void main(String[] args) { HashMap map = new HashMap(); map.put("hello", "1234"); map.put("hi", "1111"); // 무시됨 map.put("hi", "1234"); // 화면으로부터 라인단위로 입력받는다. Scanner s = new Scanner(System.in); while (true) { System.out.println("id와 password를 입력해주세요."); System.out.println("id : "); String id = s.nextLine().trim(); // trim()은 공백제거 메소드 System.out.println("password : "); String password = s.nextLine().trim(); System.out.println(); if (!map.containsKey(id)) { System.out.println("입력하신 id는 존재하지 않습니다." + " 다시 입력해주세요."); continue; } else { if (!(map.get(id).equals(password))) { System.out.println("비밀번호가 일치하지 않습니다. 다시 입력해주세요."); } else { System.out.println("id와 비밀번호가 일치합니다."); break; } } } } } | cs |
Result)
3개의 데이터 쌍을 저장했지만 실제로는 2개 밖에 저장되지 않은 이유는 중복된 키가 이기 때문이다.
세 번째로 저장한 데이터의 키인 'hi'는 이미 존재하기 때문에 새로 추가되는 대신 기존의 값을 덮어썼다.
그래서 키 'hi'에 연결된 값은 '1234'가 된다.
Source 02) HashMapEx02.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | package hashMapEx; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class HashMapEx02 { public static void main(String[] args) { HashMap map = new HashMap(); map.put("임승한 ", new Integer(90)); // 무시됨 map.put("임승한 ", new Integer(100)); map.put("홍길동 ", new Integer(100)); map.put("춘향이 ", new Integer(90)); map.put("김두환 ", new Integer(90)); // entrySet()을 이용해서 키와 값을 함께 읽어옴 Set set = map.entrySet(); Iterator it = set.iterator(); while (it.hasNext()) { Map.Entry e = (Map.Entry) it.next(); System.out.println("이름 : " + e.getKey() + "점수 : " + e.getValue()); } // keySet()을 이용해서 키값을 읽어옴 set = map.keySet(); System.out.println("참가자 명단 : " + set); // values()을 이용해서 키값을 읽어옴 Collection value = map.values(); it = value.iterator(); int total = 0; while (it.hasNext()) { Integer i = (Integer) it.next(); total += i.intValue(); } System.out.println("총점 : " + total); System.out.println("평균 : " + (float) total / set.size()); System.out.println("최고점수 : " + Collections.max(value)); System.out.println("최저점수 : " + Collections.max(value)); } } | cs |
Result)
1 2 3 4 5 6 7 8 9 | 이름 : 춘향이 점수 : 90 이름 : 홍길동 점수 : 100 이름 : 김두환 점수 : 90 이름 : 임승한 점수 : 100 참가자 명단 : [춘향이 , 홍길동 , 김두환 , 임승한 ] 총점 : 380 평균 : 95.0 최고점수 : 100 최저점수 : 90 | cs |
Source 03) HashMapEx03.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | package hashMapEx; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class HashMapEx03 { static HashMap phoneBook = new HashMap(); public static void main(String[] args) { addPhoneNo("친구", "임승한", "010-0000-0001"); addPhoneNo("친구", "홍길동", "010-0000-0002"); addPhoneNo("친구", "아무개", "010-0000-0003"); addPhoneNo("회사", "김사원", "010-0000-0004"); addPhoneNo("회사", "이사원", "010-0000-0005"); addPhoneNo("회사", "나사원", "010-0000-0006"); addPhoneNo("회사", "인사원", "010-0000-0007"); addPhoneNo("세탁", "010-0000-0000"); printList(); } /* * HashMap은 데이터의 키와 값을 모두 Object타입으로 저장하기 때문에 HashMap의 값(value)으로 HashMap을 * 다시 저장할 수 있다. 이렇게 함으로써 하나의 키에 다시 복수의 데이터를 저장할 수 있다. 먼저 전화번호를 저장할 그룹을 만들고 * 그룹 안에 다시 이름과 전화번호를 저장하도록 했다. 이때 이름대신 전화번호를 키로 사용했다는 것을 확인하자. 이름은 동명이인이 있을 * 수 있지만 전화번호는 유일하기 때문이다. */ // 그룹을 추가하는 메서드 private static void addGroup(String groupName) { if (!phoneBook.containsKey(groupName)) phoneBook.put(groupName, new HashMap()); } // 그룹에 전화번호를 추가하는 메서드 private static void addPhoneNo(String groupName, String name, String tel) { addGroup(groupName); HashMap group = (HashMap) phoneBook.get(groupName); group.put(tel, name); // 이름은 중복될 수 있으니 전화번호를 key로 저장한다. } private static void addPhoneNo(String name, String tel) { addPhoneNo("기타", name, tel); } // 전화번호부 전체를 출력하는 메서드 // entrySet() : 키(key)와 값(value)을 함께 읽어온다. /* HashMap을 중첩으로 사용했기 때문에 Iterator도 두번 사용되었다. */ private static void printList() { Set set = phoneBook.entrySet(); Iterator it = set.iterator(); while (it.hasNext()) { Map.Entry e = (Map.Entry) it.next(); Set subSet = ((HashMap) e.getValue()).entrySet(); Iterator subIt = subSet.iterator(); System.out.println(" * " + e.getKey() + "[" + subSet.size() + "]"); while (subIt.hasNext()) { Map.Entry subE = (Map.Entry) subIt.next(); String telNo = (String) subE.getKey(); String name = (String) subE.getValue(); System.out.println(name + " " + telNo); } System.out.println(); } } } | cs |
Result)
1 2 3 4 5 6 7 8 9 10 11 12 13 | * 기타[1] 세탁 010-0000-0000 * 친구[3] 홍길동 010-0000-0002 임승한 010-0000-0001 아무개 010-0000-0003 * 회사[4] 나사원 010-0000-0006 이사원 010-0000-0005 인사원 010-0000-0007 김사원 010-0000-0004 | cs |
Source 04) HashMapEx04.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | package hashMapEx; import java.awt.print.Printable; import java.util.HashMap; import java.util.Iterator; import java.util.Map; public class HashMapEx04 { public static void main(String[] args) { String[] data = { "A", "K", "A", "A", "K", "D", "K", "A", "K", "K", "K", "K", "Z", "D" }; HashMap map = new HashMap(); for (int i = 0; i < data.length; i++) { /* * HashMap에 같은 문자열이 키로 저장되어 있는지 containKey()로 확인하여 * 이미 저장되어 있는 문자열이면 값을 1증가시킨다. */ if (map.containsKey(data[i])) { Integer value = (Integer) map.get(data[i]); map.put(data[i], new Integer(value.intValue() + 1)); } else { /* * 문자열 배열에 담긴 문자열을 하나씩 읽어서 HashMap에 키로 저장하고 값으로 1을 저장한다. */ map.put(data[i], new Integer(1)); } } Iterator it = map.entrySet().iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); int value = ((Integer) entry.getValue()).intValue(); System.out.println(entry.getKey() + " : " + PrintBar('#', value) + " " + value); } } private static Object PrintBar(char ch, int value) { char[] bar = new char[value]; for (int i = 0; i < bar.length; i++) { bar[i] = ch; } return new String(bar); // String(char[] chArr) } } | cs |
Result)
1 2 3 4 | A : #### 4 D : ## 2 Z : # 1 K : ####### 7 | cs |
문자열 배열에 담긴 문자열을 하나씩 읽어서 HashMap에 키로 저장하고 값으로 1을 저장한다.
HashMap에 같은 문자열이 키로 저장되어 있는지 containKey()로 확인하여 이미 저장되어 있는 문자열이면 값을 1증가시킨다.
그리고 그 결과를 printBar()을 이용해서 그래프로 표현했다. 이렇게 하면 문자열 배열에 담긴 문자열들의 빈도수를 구할 수 있다.
한정된 범위 내에 있는 순차적인 값들의 빈도수는 배열을 이용하지만, 이처럼 한정되지 않은 범위의 비순차적인 값들의 빈도수는 HashMap을 이용해서 구할 수 있다.
- 출처 및 참고자료 : JAVA의정석(남궁성 저)
댓글