코딩/Java

Java 6 : Map, Hash, HashTable

americanoallday 2025. 2. 7. 16:03

Map 자료형 (Key-Value 자료구조)

 Map은 “Key-Value(키-값)” 쌍으로 데이터를 저장하는 자료구조

✔ “키(Key)“를 이용해 “값(Value)“을 저장하고 검색할 수 있음

✔ 키는 중복될 수 없지만, 값은 중복 가능

✔ 대표적인 구현체: HashMap, TreeMap, LinkedHashMap

Map<String, Integer> map = new HashMap<>();

 

Map 주요 기능

put(key, value) : 키-값 추가

get(key) : 해당 키의 값을 가져오기

remove(key) : 해당 키 삭제

containsKey(key) : 키 존재 여부 확인

containsValue(value) : 값 존재 여부 확인

size() : 요소 개수 반환

keySet() : 모든 키 반환

values() : 모든 값 반환

Map.of() : Java 9에서 추가된 기능, put()을 여러 번 호출하지 않고 한 번에 Map을 만들 수 있음, 생성된 Map은 수정할 수 없음(Immutable, 읽기 전용)

더보기
import java.util.Map;

public class MapOfExample {
    public static void main(String[] args) {
        // ✅ 불변 Map 생성 (Java 9 이상에서 사용 가능)
        Map<String, Integer> beverages = Map.of(
                "사이다", 1700,
                "콜라", 1900,
                "식혜", 2500,
                "솔의눈", 3000
        );

        // ✅ 값 출력
        System.out.println(beverages);

        // ✅ 특정 값 가져오기
        System.out.println("콜라 가격: " + beverages.get("콜라"));

        // ❌ 값 변경 시도 (예외 발생!)
        beverages.put("환타", 1800); // UnsupportedOperationException 발생!
    }
}

 

HashMap : 빠른 검색(O(1)), 순서 보장 X

TreeMap : 키를 정렬(O(log n)), 이진 트리

LinkedHashMap : 입력 순서 유지

* HashMap, LinkedHashMap 차이점 

HashMap : ❌순서 보장 X(키-값 저장 시마다 랜덤한 순서)

더보기

HashMap이 순서를 보장하지 않는 이유

HashMap은 내부적으로 “해시 테이블(Hash Table)” 구조를 사용

✔ 데이터는 키(Key)를 해싱(Hashing)하여 특정 위치(Bucket)에 저장됨

새로운 데이터를 추가할 때마다 해시 충돌, 리사이징 등의 과정으로 기존 요소의 위치가 변경될 수 있음

즉, 입력 순서대로 저장되지 않고, 내부적으로 해시 값에 따라 저장되므로 순서가 보장되지 않음

 

HashMap은 내부적으로 배열 + 연결 리스트(또는 트리) 구조를 사용

 

해시(Hash): 데이터를 고유한 숫자로 변환하는 알고리즘

해시 값(Hash Value): 변환된 고유한 숫자

해시 테이블(Hash Table): 해시 값을 이용해서 데이터를 저장하고 검색하는 자료구조

 

해시 테이블(Hash Table)

✔ 해시 값을 이용하여 데이터를 빠르게 저장하고 검색하는 자료구조

✔ 배열 + 해시 함수(Hash Function)를 이용하여 데이터를 저장

✔ 키(Key)를 해싱(Hashing)하여 특정 위치(Bucket)에 저장

✔ 빠른 검색(O(1))이 가능

✔ 대표적인 구현체: HashMap, Hashtable

 

해시 충돌(Hash Collision)이란?

✔ 다른 키(Key)가 같은 해시 값을 가질 경우를 “해시 충돌(Hash Collision)“이라고 함

✔ 충돌이 발생하면 “연결 리스트(Linked List)” 또는 “트리(Tree)“를 사용하여 해결

LinkedHashMap :⭕입력된 순서 유지(데이터를 넣은 순서대로 저장됨)

더보기

LinkedHashMap에서 순서가 유지되는 이유

LinkedHashMap은 “이중 연결 리스트(Doubly Linked List) + 해시 테이블”을 사용

데이터가 추가될 때마다 “이전 요소”와 “다음 요소”를 연결하는 포인터를 유지

즉, 새로운 요소를 추가해도 원래 입력 순서를 유지할 수 있음

 

LinkedHashMap“이전 요소 ↔ 현재 요소 ↔ 다음 요소”로 연결된 구조

 

 

HashMap 예제

import java.util.HashMap;
import java.util.Map;

public class MapExample{
    public static void main(String[] args){
        // ✅ HashMap 객체 생성 (키: String, 값: Integer)
        Map<String, Integer> studentScores = new HashMap<>();

        // ✅ 데이터 추가 (put)
        studentScores.put("Alice", 90);
        studentScores.put("Bob", 85);
        studentScores.put("Charlie", 92);

        // ✅ 값 가져오기 (get)
        System.out.println("Alice의 점수: " + studentScores.get("Alice")); // 90

        // ✅ 키 존재 여부 확인 (containsKey)
        System.out.println("Bob이 있는가? " + studentScores.containsKey("Bob")); // true

        // ✅ 모든 키 출력 (keySet)
        System.out.println("모든 학생: " + studentScores.keySet());

        // ✅ 모든 값 출력 (values)
        System.out.println("모든 점수: " + studentScores.values());

        // ✅ 요소 삭제 (remove)
        studentScores.remove("Bob");
        System.out.println("Bob 삭제 후: " + studentScores);
    }
}
Alice의 점수: 90
Bob이 있는가? true
모든 학생: [Alice, Bob, Charlie]
모든 점수: [90, 85, 92]
Bob 삭제 후: {Alice=90, Charlie=92}

 

treeMap 예제

import java.util.TreeMap;
import java.util.Map;

public class TreeMapExample{
    public static void main(String[] args){
        Map<Integer, String> treeMap = new TreeMap<>();

        treeMap.put(3, "세번째");
        treeMap.put(1, "첫번째");
        treeMap.put(2, "두번째");

        System.out.println(treeMap); // {1=첫번째, 2=두번째, 3=세번째} (정렬됨)
    }
}

 

LinkedHashMap 예제

import java.util.LinkedHashMap;
import java.util.Map;

public class LinkedHashMapExample{
    public static void main(String[] args){
        // ✅ LinkedHashMap 생성 (입력 순서 유지)
        Map<String, Integer> linkedHashMap = new LinkedHashMap<>();

        // ✅ 키-값 추가 (입력된 순서대로 저장됨)
        linkedHashMap.put("Apple", 100);
        linkedHashMap.put("Banana", 50);
        linkedHashMap.put("Cherry", 75);

        // ✅ 모든 요소 출력 (입력된 순서 유지)
        System.out.println("LinkedHashMap: " + linkedHashMap);

        // ✅ 특정 키의 값 가져오기
        System.out.println("Apple 가격: " + linkedHashMap.get("Apple"));

        // ✅ 키 존재 여부 확인
        System.out.println("Cherry가 있는가? " + linkedHashMap.containsKey("Cherry"));

        // ✅ 모든 키 출력 (입력 순서 유지)
        System.out.println("모든 키: " + linkedHashMap.keySet());

        // ✅ 모든 값 출력 (입력 순서 유지)
        System.out.println("모든 값: " + linkedHashMap.values());

        // ✅ 요소 삭제
        linkedHashMap.remove("Banana");
        System.out.println("Banana 삭제 후: " + linkedHashMap);
    }
}
LinkedHashMap: {Apple=100, Banana=50, Cherry=75}
Apple 가격: 100
Cherry가 있는가? true
모든 키: [Apple, Banana, Cherry]
모든 값: [100, 50, 75]
Banana 삭제 후: {Apple=100, Cherry=75}

 

 

Java 웹 컴파일러

https://www.mycompiler.io/ko/new/java

 

자판기 주문하기 예제 : Map 데이터구조, Map.get(), Map.getKey(), Map.getValue(), Scanner 활용

1 자판기 메뉴 출력

2. 음료 선택(유무 확인)

3. 지불 금액 입력 받고 잔액 거슬러주기

 

Scanner

더보기

사용자 입력을 받는 클래스 (System.in)

 

스캐너 함수

next() : 공백 전까지 입력 받음

nextLine() : 한 줄 전체 입력 받음

nextInt() : 정수 입력 (버퍼 문제 발생 가능)

hasNext() : 다음 입력이 있는지 확인 (반복 입력 가능)

* Scanner를 사용한 파일 입력 : new Scanner(new File("data.txt")) 사용

 

정답

더보기
import java.util.*;
import java.lang.*;
import java.io.*;

// The main method must be in a class named "Main".
class Main {
    public static void main(String[] args) {
        Map<String, Integer> beverages = Map.of(
                "사이다", 1700,
                "콜라", 1900,
                "식혜", 2500,
                "솔의눈", 3000
        );
        System.out.println("[자판기 메뉴]");
        for (Map.Entry<String, Integer> entry : beverages.entrySet()) {
            System.out.println(entry.getKey() + entry.getValue());
        }
        System.out.println("주문하실 음료 이름을 적어주세요");
        
        Scanner scanner = new Scanner(System.in);
        String userChoice = scanner.nextLine();

        if(beverages.containsKey(userChoice))
        {
            System.out.println("지불 금액 입력해 주세요");
            int userPayAmount = scanner.nextInt();

            if(userPayAmount < beverages.get(userChoice)){
                System.out.println("돈이 부족합니다.");
            }else{
                System.out.println("잔액: " + (userPayAmount - beverages.get(userChoice)));
            }
        }else{
            System.out.println("입력하신 음료수는 없습니다.");
            return;
        }
    }
}

 

단어 맞추기 게임 예제 : Character.isLetter(), charAt(0)

1. 랜덤한 단어 선택 후 영어 자리수를 화면에 표시

2. A-Z 알파벳 중 하나 입력

- 알파벳이 아니라면 다시 입력받기 : Charactor.isLetter() 이용

- 입력 글자가 한글자가 아니라면 다시 입력 받기

- 이미 입력한 알파벳이라면 다시 입력 받기

3. 입력한 알파벳이 단어에 포함된 경우 알파벳이 들어간 자리를 전부 보여주고 다시 입력 받기

4. 입력한 값이 미포함된 경우 기회 -1 차감

5. 9번 틀리면 게임오버, 9번 이내에 맞추면 승리

더보기

charAt(0) → 문자열에서 첫 번째 문자를 가져오는 메서드

Character.isLetter(char c) → 주어진 문자가 “문자(알파벳 또는 유니코드 문자)“인지 확인하는 메서드

import java.util.*;
import java.lang.*;
import java.io.*;


// The main method must be in a class named "Main".
class Main {
    /**
 * @param args
 */
public static void main(String[] args) {
        String[] words = {
        "airplane",
        "apple",
        "arm",
        "bakery",
        "banana",
        "bank",
        "bean",
        "belt",
        "bicycle",
        "biography",
        "blackboard",
        "boat",
        "bowl",
        "broccoli",
        "bus",
        "car",
        "carrot",
        "chair",
        "cherry",
        "cinema",
        "class",
        "classroom",
        "cloud",
        "coat",
        "cucumber",
        "desk",
        "dictionary",
        "dress",
        "ear",
        "eye",
        "fog",
        "foot",
        "fork",
        "fruits",
        "hail",
        "hand",
        "head",
        "helicopter",
        "hospital",
        "ice",
        "jacket",
        "kettle",
        "knife",
        "leg",
        "lettuce",
        "library",
        "magazine",
        "mango",
        "melon",
        "motorcycle",
        "mouth",
        "newspaper",
        "nose",
        "notebook",
        "novel",
        "onion",
        "orange",
        "peach",
        "pharmacy",
        "pineapple",
        "plate",
        "pot",
        "potato",
        "rain",
        "shirt",
        "shoe",
        "shop",
        "sink",
        "skateboard",
        "ski",
        "skirt",
        "sky",
        "snow",
        "sock",
        "spinach",
        "spoon",
        "stationary",
        "stomach",
        "strawberry",
        "student",
        "sun",
        "supermarket",
        "sweater",
        "teacher",
        "thunderstorm",
        "tomato",
        "trousers",
        "truck",
        "vegetables",
        "vehicles",
        "watermelon",
        "wind",
        };
        Random random = new Random();
        String randomWord = words[random.nextInt(words.length)];
        System.out.println("글자 수 : " + randomWord.length());
        
        char[] displayWord = new char[randomWord.length()];
        for(int i = 0; i < displayWord.length; i++){
                displayWord[i] = '_';
                System.out.print(displayWord[i] + " ");
        }

        int count = 9;
        Scanner scanner = new Scanner(System.in);
        String userWord;

        while (count>0) {
                System.out.println("단어를 입력해주세요 : ");
                userWord = scanner.nextLine();
                if(userWord.length() != 1 || !userWord.matches("[a-zA-Z]")){
                        System.out.println("한 글자(알파벳) 입력해주세요");
                        continue;
                }
                boolean isCorrect = false;
                for(int i = 0; i < randomWord.length(); i++){
                        if(randomWord.charAt(i) == userWord.charAt(0)){
                        displayWord[i] = userWord.charAt(0);
                        isCorrect = true;
                        }
                }
                if(!isCorrect){
                        count--;
                        System.out.println("틀렸습니다. 남은 기회 : " + count);
                }
                for(int i = 0; i < displayWord.length; i++){
                        System.out.print(displayWord[i] + " ");
                }
                System.out.println();
                if(randomWord.equals(String.valueOf(displayWord))){
                        System.out.println("정답입니다.");
                        break;
                }
                if(count == 0){
                        System.out.println("기회를 모두 소진하였습니다. 정답은 " + randomWord + "입니다.");
                }
        }
    }
}

 

가위 바위 보 대결 예제

1. 5번의 가위바위보 게임을 진행

2. 유저는 매 판마다 가위, 바위, 보 중 하나를 입력 (다른 값 입력 시 잘못된 값 입력했습니다. 출력 및 재입력 받기)

3. 컴퓨터는 매 판마다 랜덤하게 가위바위보 선택

4. 매 판마다 승패 결과 출력

5. 승리한 횟수에 따른 경품 출력

더보기
        Map<Integer, String> gifts = new HashMap<>();
        gifts.put(0, "꽝");
        gifts.put(1, "곰돌이 인형");
        gifts.put(2, "놀이공원 입장권");
        gifts.put(3, "괌 항공 투어권");
        gifts.put(4, "비행기 + 호텔 숙박권");
        gifts.put(5, "500만원");

        System.out.println("Game Start");
        String[] rsp = {"가위", "바위", "보"};
        Random random = new Random();
        String userRsp;
        String computerRsp; 

        Scanner scanner = new Scanner(System.in);

        int count = 5;
        int winCout = 0;

        while(count > 0){
                System.out.println("가위, 바위, 보 중 하나를 입력해주세요");
                userRsp = scanner.nextLine();
                computerRsp = rsp[random.nextInt(rsp.length)];
                
                if(!userRsp.equals("가위") && !userRsp.equals("바위") && !userRsp.equals("보")){
                        System.out.println("잘못된 입력입니다. 가위, 바위, 보 중 하나를 입력해주세요");
                        continue;
                }

                switch(userRsp){
                        case "가위":
                                if(computerRsp.equals("가위")){
                                        System.out.println("비겼습니다.");
                                }else if(computerRsp.equals("바위")){
                                        System.out.println("졌습니다.");
                                }else{
                                        System.out.println("이겼습니다.");
                                        winCout++;
                                }
                                break;
                        case "바위":
                                if(computerRsp.equals("가위")){
                                        System.out.println("이겼습니다.");
                                        winCout++;
                                }else if(computerRsp.equals("바위")){
                                        System.out.println("비겼습니다.");
                                }else{
                                        System.out.println("졌습니다.");
                                }
                                break;
                        case "보":
                                if(computerRsp.equals("가위")){
                                        System.out.println("졌습니다.");
                                }else if(computerRsp.equals("바위")){
                                        System.out.println("이겼습니다.");
                                        winCout++;
                                }else{
                                        System.out.println("비겼습니다.");
                                }
                                break;
                        default:
                                System.out.println("가위, 바위, 보 중 하나를 입력해주세요");
                                break;
                }
                count--;
                System.out.println("남은 기회 : " + count);

                if(count == 0 && winCout != 0){
                        System.out.println("기회를 모두 소진하였습니다.");
                        System.out.println("축하합니다! 총 " + winCout + " 회 승리하여 경품으로 [" + gifts.get(winCout) + "] 을 획득하셨습니다!");
                        break;
                }
                if(count == 0 && winCout == 0){
                        System.out.println("기회를 모두 소진하였습니다. 경품에 당첨되지 못하셨습니다.");
                }
        }

'코딩 > Java' 카테고리의 다른 글

[Java] StringBuilder란  (0) 2025.04.14
default 메서드란  (0) 2025.04.03
Java 5 : 객체지향(OOP : Object-Oriented-Programming), 추상화, 인터페이스  (0) 2025.02.06
Java 4 : 조건문, 반목문, 배열  (0) 2025.02.05
Java 3 : 연산자  (0) 2025.02.05