Java 컬렉션 : HashMap

I C-AN·2021년 8월 16일
0

Java

목록 보기
26/26
post-thumbnail

📚 Map : HashMap

Map 인터페이스를 구현해서 데이터를 키와 값의 쌍으로 저장한다. 또한 해싱(Hashing)을 사용하기 때문에 많은 양의 데이터를 검색하는 데 용이하다. 순서를 유지해서 저장해야 한다면 LinkedHashMap을 사용하면 된다.

HashMap의 키와 값

HashMap map = new HashMap();
map.put("myId", "1234"); // map은 put()으로 데이터를 저장
map.put("asdf", "1234"); // value의 중복은 허용
map.put("asdf", "4234"); // key의 중복은 허용하지 않음
// 결과
{myId=1234, asdf=4234} // key가 중복되면 나중에 넣은 value 값이 저장된다
  • key : 컬렉션 내의 key 중에서 유일해야 한다.
  • value : key와 달리 데이터의 중복을 허용한다.

HashMap은 키와 값을 Object 타입으로 저장하기 때문에 어떠한 객체든 저장할 수 있지만 키는 주로 String으로 통일해서 사용한다.

해싱과 해시함수

해싱이란 해시함수를 이용해서 데이터를 해시테이블에 저장하고 검색하는 기법이다. 해시함수는 데이터가 저장되어 있는 곳을 알려주기 때문에 원하는 데이터를 빠르게 찾을 수 있다. 해싱의 자료구조는 배열과 LinkedList의 조합으로 구성되어 있다.

출처 : Eecs Umich

  1. 키로 해시함수를 호출해서 해시코드를 얻는다.
  2. 해시코드에 대응하는 LinkedList를 배열에서 찾는다.
  3. LinkedList에서 키와 일치하는 데이터를 찾는다.

해시함수는 같은 키에 대해 항상 같은 해시코드를 반환해야 한다. 서로 다른 키더라도 같은 값의 해시코드를 반환할 수도 있다.

HashMap 생성자

HashMap()
HashMap(int initialCapacity) // 지정된 값을 초기용량으로 하는 HashMap 생성
HashMap(int initialCapacity, float loadFactor) // 용량을 늘릴 시점을 정함
HashMap(Map m) // 지정된 Map의 모든 요소를 포함하는 HashMap

HashMap 주요 메서드

데이터 변경

Object put(Object key, Object value)
void putAll(Map m)
Object remove(Object key)
Object replace(Object key, Object value)
boolean replace(Object key, Object oldValue, Object newValue)
  • put() , putAll() : 지정한 키와 값 아니면 Map의 모든 요소를 저장한다.
  • remove() : 지정된 키로 저장된 데이터를 제거한다.
  • replace() : 지정된 키의 값을 교체한다.

데이터 반환

Set entrySet()
Set keySet()
Collection values()
Object get(Object key)
boolean containsKey(Object key)
boolean containsValue(Object value)
  • entrySet() : HashMap에 저장된 키와 값을 Entry의 형태로 결합하여 Set으로 반환한다.
  • keySet() : HashMap에 저장된 모든 키를 저장한 Set으로 반환한다.
  • values() : HashMap에 저장된 모든 값을 컬렉션의 형태로 반환한다.
  • get() : 지정된 키의 값을 반환한다.
  • contiansKey() , containsValue() : 지정한 키나 값이 포함되어 있는 지 알려준다.

📖 예제

id 인증하기

HashMap 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("id와 password를 입력해주세요.");
	System.out.print("id :");
	String id = s.nextLine().trim(); // 공백 제거

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

	if(!map.containsKey(id)) { // map에 id 포함 여부를 확인
		System.out.println("입력하신 id는 존재하지 않습니다. 다시 입력해주세요.");
		continue; // 다시 while문 실행
	} else {
		if(!(map.get(id)).equals(password)) { // id의 값이 입력값과 일치하는 지 확인
			System.out.println("비밀번호가 일치하지 않습니다. 다시 입력해주세요.");
		} else {
			System.out.println("id와 비밀번호가 일치합니다.");						
			break;
		}
	}
}
// 결과
id와 password를 입력해주세요.
id :test
password :1234

입력하신 id는 존재하지 않습니다. 다시 입력해주세요.
id와 password를 입력해주세요.
id :myId
password :1111

비밀번호가 일치하지 않습니다. 다시 입력해주세요.
id와 password를 입력해주세요.
id :myId
password :1234

id와 비밀번호가 일치합니다.

데이터 저장하고 읽어오기

HashMap map = new HashMap();
map.put("Alistar", new Integer(90));
map.put("Darius", new Integer(100));
map.put("Cho`gath", new Integer(100));
map.put("Darius", new Integer(80)); // 키가 일치하여 값이 덮어써짐
map.put("Echo", new Integer(90));

Set set = map.entrySet(); // 키와 값을 Entry 형태로 Set에 반환
Iterator it = set.iterator();

while(it.hasNext()) {
	Map.Entry e = (Map.Entry)it.next();
	// 키와 값을 하나씩 출력
	System.out.println("이름 : "+ e.getKey() + ", 점수 : " + e.getValue());
}

set = map.keySet(); // 키만 set에 반환
System.out.println("참가자 명단 : " + set);

Collection values = map.values(); // 모든 값만 가져오기
it = values.iterator();

int total = 0;

while(it.hasNext()) {
	int i = (int)it.next();
	total += i.intValue(); // 값의 총합을 저장
}

System.out.println("총점 : " + total);
System.out.println("평균 : " + (float)total/set.size()); // set의 size만큼 나누기
System.out.println("최고점수 : " + Collections.max(values));
System.out.println("최저점수 : " + Collections.min(values));
// 결과
이름 : Echo, 점수 : 90
이름 : Darius, 점수 : 80
이름 : Cho`gath, 점수 : 100
이름 : Alistar, 점수 : 90
참가자 명단 : [Echo, Darius, Cho`gath, Alistar]
총점 : 360
평균 : 90.0
최고점수 : 100
최저점수 : 80

전화번호부 만들기

class prac {
	static HashMap phoneBook = new HashMap();

	public static void main(String[] args) {
		addPhoneNo("친구", "가렌", "010-111-1111");
		addPhoneNo("친구", "그라가스", "010-222-2222");
		addPhoneNo("친구", "다리우스", "010-333-3333");
		addPhoneNo("회사", "비에고", "010-444-4444");
		addPhoneNo("회사", "아크샨", "010-555-5555");
		addPhoneNo("회사", "루시안", "010-666-6666");
		addPhoneNo("회사", "시비르", "010-777-7777");
		addPhoneNo("세탁", "010-888-8888");

		printList();
	}

	// 그룹을 추가하는 메서드
	static void addGroup(String groupName) {
		if (!phoneBook.containsKey(groupName))
			// HashMap의 값으로 HashMap을 사용할 수 있다
			phoneBook.put(groupName, new HashMap());
	}

	// 그룹에 전화번호를 추가하는 메서드
	static void addPhoneNo(String groupName, String name, String tel) {
		addGroup(groupName);
		// 그룹이름으로 HashMap 생성
		HashMap group = (HashMap) phoneBook.get(groupName);
		group.put(tel, name); // 이름은 중복될 수 있으니 전화번호를 key로 저장
	}

	// 그룹이름을 정의하지 않으면 기타 그룹을 생성
	static void addPhoneNo(String name, String tel) {
		addPhoneNo("기타", name, tel);
	}

	// 전화번호부 전체를 출력하는 메서드
	static void printList() {
		// 그룹과 HashMap을 Set 타입으로 저장
		Set set = phoneBook.entrySet();
		Iterator it = set.iterator();

		while (it.hasNext()) {
			Map.Entry e = (Map.Entry) it.next();

			// 그룹 안에 있는 HashMap의 키와 값을 Set 타입으로 저장
			Set subSet = ((HashMap) e.getValue()).entrySet();
			Iterator subIt = subSet.iterator();

			System.out.println(" * " + e.getKey() + "[" + subSet.size() + "]");
            
			// HashMap의 정보 반환
			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();
		}
	}
}
// 결과
 * 기타[1]
세탁 010-888-8888

 * 친구[3]
가렌 010-111-1111
그라가스 010-222-2222
다리우스 010-333-3333

 * 회사[4]
시비르 010-777-7777
비에고 010-444-4444
아크샨 010-555-5555
루시안 010-666-6666

빈도수 계산하기

class prac {
	public static void main(String[] args) {
		String[] data = { "A", "K", "A", "K", "D", "K", "A", "K", "K", "K", "Z", "D" };

		HashMap map = new HashMap();

		for (int i = 0; i < data.length; i++) {
			if (map.containsKey(data[i])) { // map에 포함된 키라면 실행
				int value = (int) map.get(data[i]);
				map.put(data[i], value + 1)); // 해당 키의 값에 1을 추가
			} else {
				map.put(data[i], 1);
			}
		}

		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);
		}
	}

	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); // String(char[] chArr)
	}
}
// 결과
A : ### 3
D : ## 2
Z : # 1
K : ###### 6
profile
할 수 있다

0개의 댓글