관리 메뉴

나구리의 개발공부기록

자바의 정석 기초편 ch11 - 46 ~ 51[HashMap과 Hashtable] 본문

유튜브 공부/JAVA의 정석 기초편(유튜브)

자바의 정석 기초편 ch11 - 46 ~ 51[HashMap과 Hashtable]

소소한나구리 2023. 12. 12. 18:35

1) HashMap과 Hashtable

  • Hashtable은 동기화가 되어있고 HashMap은 동기화가 되어있지 않음
  • Map인터페이스를 구현하였으며 데이터를 키와 값의 쌍으로 저장함
  • key - 중복불가, value - 중복허용
  • HashMap은 Map인터페이스를 구현한 대표적인 컬렉션 클래스이며 순서를 유지하려면 LinkedHashMap클래스를 사용하면 됨

(1) HashMap의 키(key)와 값(value)

  •  Hash로 시작하는 컬렉션들은 해싱(hashing) 기법으로 데이터를 저장하며 데이터가 많아도 검색이 빠른 특징을 가지고 있음
// HashMap 사용방법
HashMap map = new HashMap();
map.put("myID", "1234");
map.put("asdf", "1111");
map.put("asdf", "1234");	// key중복 -> 기존의 값을 덮어씀

/*
결과
 키       값
myID    1234
asdf    1234	// 기존의 값을 새로운 값으로 덮어씀 - 주의
*/

2) TreeMap

  • TreeSet과 동일 특성을 가지고 있음(이진탐색트리)
  • Key를 기준으로 정렬됨
  • HashMap보다 데이터 추가, 삭제에 시간이 더 걸림

3) 해싱(hashing)

  • 해쉬함수(hash function)로 해시테이블(hash table)에 데이터를 저장 및 검색
  • Objects.hash()로 해시코드를 생성 후 저장위치를 해쉬코드로 표현(배열의 index의 기능을 해쉬코드로 함)
  • 해시테이블은 배열과 링크드리스트가 조합된 2차원 배열의 형태로 배열의장점(접근성)과 LinkedList의장점(변경유리)을 조합한 자료구조임

좌 / hashing , 우 / 해시테이블 설명

 

(1) 해시테이블에 저장된 데이터를 가져오는 과정

  1. key로 해시함수를 호출하여 해시코드(배열의 index의 기능)를 반환
  2. 해시코드에 대응하는 LinkedList를 배열에서 검색
  3. LinkedList에서 키와 일치하는 데이터를 검색

 ** 참고

  • 해시함수는 같은 키에 대해서 항상 같은 해시코드를 반환해야함
  • 서로 다른 키일지라도 같은 값의 해시코드를 반환할 수 있음(같은 인덱스에 서로다른 키값들이 존재 할 수 있다는 뜻)

4) HashMap의 주요 메서드

(1) 생성자

  • HashMap()
  • HashMap(int initialCapacity) : HashMap의 초기용량 설정
  • HashMap(int initialCapacity, float loadFactor) : 언제 용량을 늘릴건지 설정(loadFactor 0.8 -> 80%)
  • HashMap(Map m) : 다른 Map을 해쉬맵으로 변경

(2) 메서드

HashMap 주요 메서드
설명
전체삭제 void clear() Map의 모든 객체를 삭제
검색

boolean containsKeys(Object key) 지정된 key객체와 일치하는 Map의 key객체가 있는지 확인
boolean containsValue(Object value) 지정된 value객체와 일치하는 Map의 value객체가 있는지 확인
Object get(Object key) 지정된 key객체에 대응하는 value객체를 찾아서 반환
Object getOrDefault(Object key , Object  defaultValue) 지정된 키(key)의 값(객체)을 반환, 키를 못찾으면 기본값(defaultValue)으로 지정된 객체를 반환
읽기

Set entrySet() Map에 저장되어있는 key-value쌍을 Map.entry타입의 객체로 저장한 Set으로 반환
Set keySet() Map에 저장된 모든 key객체를 반환
Collection values() Map에 저장된 모든 value객체를 반환
(순서와 중복이 있어도, 없어도 되서 Collection타입으로 반환)
- boolean isEmpty() Map이 비어있는지 확인
추가
Object put(Object key, Object Value) Map에 value객체를 key객체에 연결(mapping)하여 저장
void putAll(Map t) 지정된 Map의 모든 key-value의 쌍을 추가
삭제 Object remove(Object key) 지정한 key객체와 일치하는 key-value객체를 삭제
변경
Object replace(Object key, Object value) 지정된 키(key)를 새로운 객체(value)로 저장
boolean replace(Object key, Object oldValue, Object newValue) 지정된 키와 객체(key, oldValue)가 모두 일치하는 경우에만 새로운 객체(newValue)로 대체
- int size() Map에 저장된 key-value쌍의 개수를 반환
복제 Object clone() 객체를 복사

 

(3) HashMap예제2

  • 아이디, 패스워드를 입력하는 예제
  • 입력되는 key의값이 중복되면 key에 대응되는 기존 value는 새로운 value로 덮어짐
import java.util.*;

class Ex11_16 {
	public static void main(String[] args) {
		HashMap map = new HashMap();
		map.put("myId", "1234");
		map.put("asdf", "1111");  // value가 1111 -> 1234로 덮어짐
		map.put("asdf", "1234");	

		Scanner s = new Scanner(System.in);	// 화면으로부터 라인단위로 입력받는다.

		while(true) {	// id와 password가 맞을 때까지 반복
			System.out.println("id와 password를 입력해주세요.");
			System.out.print("id :");
			String id = s.nextLine().trim();

			System.out.print("password :");
			String password = s.nextLine().trim();	// trim() - 앞뒤의 공백제거
			System.out.println();

			if(!map.containsKey(id)) {
				System.out.println("입력하신 id는 존재하지 않습니다. 다시 입력해주세요.");
				continue;
			} 
			
			if(!(map.get(id)).equals(password)) {
				System.out.println("비밀번호가 일치하지 않습니다. 다시 입력해주세요.");
			} else {
				System.out.println("id와 비밀번호가 일치합니다.");
				break;
			}
		} // while
	} // main의 끝
}

 

(4) HashMap예제2

  • 학생 명단 성적으로 총점, 평균 등 데이터 구하기
  • key가 중복된 김자바의 value를 덮어씀
  • iterator를 활용하여 총점과 평균을 구하는 로직
import java.util.*;

class Ex11_17 {
	public static void main(String[] args) {
		HashMap map = new HashMap();
		map.put("김자바", 90);
		map.put("김자바", 100);	// 김자바의 점수를 덮어씀
		map.put("이자바", 100);
		map.put("강자바", 80);
		map.put("안자바", 90);
		
		// map의 key와 value를 Set으로 변환하여 Iterator를 활용
		Set set = map.entrySet();
		Iterator it = set.iterator();

		while(it.hasNext()) {
			// Map 인터페이스내부에 있는 Entry인터페이스타입으로 형변환
			Map.Entry e = (Map.Entry)it.next();
            
			// getKey() - Key값 반환, getValue - Value값 반환
			System.out.println("이름 : "+ e.getKey() + ", 점수 : " + e.getValue());
		}

		set = map.keySet();
		System.out.println("참가자 명단 : " + set);
		
		// iterator를 활용하여 총점을 계산하는 로직
		Collection values = map.values();
		it = values.iterator();

		int total = 0;
		
		while(it.hasNext()) {
			int i = (int)it.next();
			total += i;
		}

		System.out.println("총점 : " + total);
		System.out.println("평균 : " + (float)total/set.size());
        
		// Collections 클래스의 max, min 메서드,
		// Comparable을 구현한 클래스의 객체이거나 두번째 인자로 Comparator로 비교기준을 제공해야 사용가능함
		System.out.println("최고점수 : " + Collections.max(values));
		System.out.println("최저점수 : " + Collections.min(values));
	}
}

/*
출력
이름 : 안자바, 점수 : 90
이름 : 김자바, 점수 : 100
이름 : 강자바, 점수 : 80
이름 : 이자바, 점수 : 100
참가자 명단 : [안자바, 김자바, 강자바, 이자바]
총점 : 370
평균 : 92.5
최고점수 : 100
최저점수 : 80
*/

 

(5) HashMap예제3

  • 빈도수 계산 예제
  • 특정 단어의 갯수가 얼마나 나오는지 계산
  • HashMap의 Key는 중복값을 허용하지 않는 것을 활용하여 동일한 키의 값이 저장되면 value의 값을 증가하는 로직으로 구성
class Ex11_18 {
	public static void main(String[] args) {
		String[] data = { "A","K","A","K","D","K","A","K","K","K","Z","D" };
		
		// 해쉬맵 생성
		HashMap map = new HashMap();
		
		// 생성된 HashMap의 key에 data의값을 저장하고 value에 갯수를 저장
		for(int i=0; i < data.length; i++) {
			if(map.containsKey(data[i])) {
				int value = (int)map.get(data[i]);
				map.put(data[i], value+1);  // 기존에 존재하는 키면 기존 값을 1증가
			} else {
				map.put(data[i], 1);	    // 기존에 존재하지 않는 키는 값을 1로 저장		
			}
		}
		
        // Iterator를 활용하여 값을 출력
		Iterator it = map.entrySet().iterator();
		while(it.hasNext()) {
			Map.Entry entry = (Map.Entry)it.next();
			int value = (int)entry.getValue();
			System.out.println(entry.getKey() 
					+ " : " + printBar('#', value) + " " + value );
		}
	} // main
		
	// Key에 저장된 단어가 배열 data에 몇개있는지 그래프로 표현하기 위한 메서드
	public static String 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);
	}
}

/*
출력값
A : ### 3
D : ## 2
Z : # 1
K : ###### 6
*/

 

** 출처 : 남궁성의 정석코딩_자바의정석_기초편 유튜브 강의