[Java] 컬렉션 프레임워크 ③

kiteB·2022년 2월 23일
0

Java2

목록 보기
12/36
post-thumbnail

[ Map 컬렉션 ]

Map 컬렉션은 키(key)와 값(value)으로 구성된 Entry 객체를 저장하는 구조를 가지고 있다.

  • 키와 값은 모두 객체로, 키는 중복 저장될 수 없지만 값은 중복 저장될 수 있다.
    • 만약 기존에 저장된 키와 동일한 키로 값을 저장하면 기존의 값은 없어지고 새로운 값으로 대치된다.
  • Map 컬렉션에는 HashMap, Hashtable, LinkedHashMap, Properties, TreeMap 등이 있다.

Map 인터페이스의 메소드

다음은 Map 컬렉션에서 공통적으로 사용 가능한 Map 인터페이스의 메소드들이다.
키로 객체들을 관리하기 때문에 키를 매개값으로 갖는 메소드가 많다.

  • Map 인터페이스가 제네릭 타입이기 때문에 메소드의 매개 변수 타입과 리턴 타입에 KV라는 타입 파라미터가 있다.
    • 구체적인 타입은 구현 객체를 생성할 때 결정된다.
  • 객체 추가는 put(), 키로 객체를 찾아올 때에는 get(), 객체 삭제는 remove() 메소드를 사용한다.

✅ 예제 | String 타입 객체 추가/찾기/삭제

Map<String, Integer> map = ~;
map.put("Java", 10);			//객체 추가
int score = map.get("Java");	//객체 찾기
map.remove("Java");				//객체 삭제

✅ 전체 객체를 하나씩 가져오고 싶은 경우

키를 알고 싶다면 get() 메소드로 간단하게 객체를 찾아오면 되지만, 저장된 전체 객체를 대상으로 하나씩 얻고 싶을 경우에는 두 가지 방법을 사용할 수 있다.

  1. keySet() 메소드로 모든 키를 Set 컬렉션으로 얻은 다음, 반복자를 통해 키를 하나씩 얻고 get() 메소드를 통해 값을 얻으면 된다.
Map<K, V> map = ~;
Set<K> keySet = map.keySet();
Iterator<K> keyIterator = keySet.iterator();

while (keyIterator.hasNext()) {
    K key = keyIterator.next();
    V value = map.get(key);
}
  1. entrySet() 메소드로 모든 Map.EntrySet 컬렉션으로 얻은 다음, 반복자를 통해 Map.Sentry를 하나씩 얻고 getKey()getValue() 메소드를 이용해 키와 값을 얻으면 된다.
Set<Map.Entry<K, V>> entrySet = map.entrySet();
Iterator<Map.Entry<K, V>> entryIterator = entrySet.iterator();

while (entryIterator.hasNext()) {
    Map.Entry<K, V> entry = entryIterator.next();
    K key = entry.getKey();
    V value = entry.getValue();
}

1. HashMap

HashMapMap 인터페이스를 구현한 대표적인 Map 컬렉션이다.

HashMap의 키로 사용할 객체는 hashCode()equals() 메소드를 재정의해서 동등 객체가 될 조건을 정해야 한다.
동등 객체, 즉 동일한 키가 될 조건은 hashCode()의 리턴값이 같아야 하고, equals() 메소드가 true를 리턴해야 한다.

주로 키 타입은 String을 많이 사용하는데, String은 문자열이 같을 경우 동등 객체가 될 수 있도록 hashCode()equals() 메소드가 재정의되어 있다.


HashMap 생성 방법

HashMap을 생성하기 위해서는 키 타입과 값 타입을 파라미터로 주고 기본 생성자를 호출하면 된다.

Map<K, V> map = new HashMap<K, V>();
  • 키와 값의 타입은 기본 타입(byte, short, int, float, double, boolean, char)을 사용할 수 없고 클래스 및 인터페이스 타입만 가능하다.
  • 키로 String 타입을 사용하고 값으로 Integer 타입을 사용하는 HashMap은 다음과 같이 생성할 수 있다.
Map<String, Integer> map = new HashMap<String, Integer>();

✅ 예제 | 이름을 키로, 점수를 값으로 저장하기

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class HashMapExample {
    public static void main(String[] args) {
        //Map 컬렉션 생성
        Map<String, Integer> map = new HashMap<String, Integer>();

        //객체 저장
        map.put("김", 80);
        map.put("이", 67);
        map.put("박", 93);
        map.put("이", 78);	//동일한 키를 가질 때, 제일 마지막에 저장한 값으로 대치됨
        System.out.println("총 Entry 수: " + map.size());

        //객체 찾기
        System.out.println("\t이: " + map.get("이"));
        System.out.println();

        //객체를 하나씩 처리
        Set<String> keySet = map.keySet();
        Iterator<String> keyIterator = keySet.iterator();

        while(keyIterator.hasNext()) {
            String key = keyIterator.next();
            Integer value = map.get(key);
            System.out.println("\t" + key + " : " + value);
        }
        System.out.println();

        //객체 삭제
        map.remove("이");
        System.out.println("총 Entry 수: " + map.size());

        //객체를 하나씩 처리
        Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
        Iterator<Map.Entry<String, Integer>> entryIterator = entrySet.iterator();

        while(entryIterator.hasNext()) {
            Map.Entry<String, Integer> entry = entryIterator.next();
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println("\t" + key + " : " + value);
        }
        System.out.println();

        //객체 전체 삭제
        map.clear();
        System.out.println("총 Entry 수 : " + map.size());
    }
}
  • 실행 결과
총 Entry 수: 3
	이: 78

	김 : 80
	이 : 78
	박 : 93

총 Entry 수: 2
	김 : 80
	박 : 93

총 Entry 수 : 0

2. Hashtable

Hashtable

  • HashtableHashMap과 동일한 내부 구조를 가지고 있다.
    • Hashtable도 키로 사용할 객체는 hashCode()equals() 메소드를 재정의해서 동등 객체가 될 조건을 정해야 한다.
  • HashMap과의 차이점은 Hashtable은 동기화(synchronized) 메소드로 구성되어 있기 때문에 멀티 스레드가 동시에 이 메소드들을 실행할 수는 없고, 하나의 스레드가 실행을 완료해야만 다른 스레드를 실행할 수 있다.
    • 그래서 멀티 스레드 환경에서 안전하게 객체를 추가/삭제할 수 있다. (스레드가 안전(thread safe)하다.)

Hashtable 생성 방법

Hashtable의 생성 방법은 HashMap과 크게 다르지 않다. 키 타입과 값 타입을 지정하고 기본 생성자를 호출하면 된다.

Map<K, V> map = new Hashtable<K, V>();
  • 키로 String 타입을 사용하고 값으로 Integer 타입을 사용하는 Hashtable은 다음과 같이 생성할 수 있다.
Map<String, Integer> map = new Hashtable<String, Integer>(); 

✅ 예제 | 아이디와 비밀번호 검사하기

키보드로 아이디와 비밀번호를 입력받아서, Hashtable에 저장되어 있는 키(아이디)와 값(비밀번호)으로 비교한 후 로그인 여부를 출력하는 예제이다.

import java.util.*;

public class HashTableExample {
    public static void main(String[] args) {
        Map<String, String> map = new Hashtable<String, String>();

        //아이디와 비밀번호 미리 저장시키기
        map.put("spring", "12");
        map.put("summer", "123");
        map.put("fail", "1234");
        map.put("winter", "12345");

        Scanner scanner = new Scanner(System.in);

        while (true) {
            System.out.println("아이디와 비밀번호를 입력해주세요.");
            System.out.print("아이디: ");
            String id = scanner.nextLine();

            System.out.print("비밀번호: ");
            String password = scanner.nextLine();
            System.out.println();

            if (map.containsKey(id)) {
                if (map.get(id).equals(password)) {
                    System.out.println("로그인 되었습니다.");
                    break;
                } else {
                    System.out.println("비밀번호가 일치하지 않습니다.");
                }
            } else {
                System.out.println("입력하신 아이디가 존재하지 않습니다.");
            }
        }
    }
}
  • 실행 결과
아이디와 비밀번호를 입력해주세요.
아이디: summer
비밀번호: 123

로그인 되었습니다.

📌 참고

현재의 Hashtable 클래스는 HashMap 클래스와 같은 동작을 하는 클래스로, Hashtable 클래스에서 사용할 수 있는 메소드도 HashMap 클래스에서 사용할 수 있는 메소드와 거의 같다. 하지만 현재에는 기존 코드와의 호환성을 위해서만 남아있으므로, Hashtable 클래스보다는 HashMap 클래스를 사용하는 것이 좋다.


[ 참고자료 ]

이것이 자바다 책
http://tcpschool.com/java/java_collectionFramework_map

profile
🚧 https://coji.tistory.com/ 🏠

0개의 댓글