[Java] Map

아투·2026년 4월 21일

Java

목록 보기
5/16
post-thumbnail

정의

  • Map은 키(Key)와 값(Value)의 쌍으로 데이터를 저장하는 자료구조이다.

  • 리스트가 무엇이 들어있는가에 집중한다면, 맵은 어떻게 찾을 것인가에 집중하는 자료구조이다.

  • 단순히 데이터를 쌓아두는 공간이 필요하다면 리스트를 써도 충분하지만, 시스템에서 특정 조건으로 데이터를 순식간에 가져오거나, 정보들 사이의 짝을 지어줘야 한다면 Map 적합하다.

  • 키(Key)

    • 데이터를 찾기 위한 유일한 식별자
    • 예: 학번, 주민번호, 상품 ID
  • 값(Value)

    • 해당 키와 연결된 실제 데이터
    • 학생 정보, 개인 정보, 상품 상세 데이터
  • 실무적으로는 정렬보다는 검색이 최우선일 때 사용하는 가장 강력한 도구이다.

주요 Map 종류 비교

HashMap

  • 가장 일반적인 Map

  • 속도가 가장 빠름 O(1), 하지만 순서 보장이 안 됨.

  • 예제 코드

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

public class MapBasicEx {
    public static void main(String[] args) {
        // 1. 선언 (Key: 상품코드, Value: 상품명)
        Map<String, String> productMap = new HashMap<>();

        // 2. 데이터 추가 (Put)
        productMap.put("P001", "MacBook Pro 16");
        productMap.put("P002", "iPhone 15 Pro");
        productMap.put("P003", "iPad Pro");

        // 3. 데이터 조회 (Get)
        String myProduct = productMap.get("P001");
        System.out.println("조회된 상품: " + myProduct); // 결과: MacBook Pro 16

        // 4. 데이터 존재 여부 확인
        if (productMap.containsKey("P002")) {
            System.out.println("아이폰 재고가 있습니다.");
        }

        // 5. 데이터 삭제
        productMap.remove("P003");

        // 6. 전체 순회 (현업 스타일)
        productMap.forEach((key, value) -> {
            System.out.println("코드: " + key + ", 이름: " + value);
        });
    }
}

LinkedHash Map

  • 입력 순서를 유지

  • 입력한 순서대로 데이터를 뽑아야 할 때 사용.

  • 예제 코드

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

public class LinkedMapEx {
    public static void main(String[] args) {
        // 입력 순서가 중요한 최근 본 상품 목록 등에 적합
        Map<String, String> lMap = new LinkedHashMap<>();

        lMap.put("First", "사과");
        lMap.put("Second", "바나나");
        lMap.put("Third", "포도");

        // 결과: First -> Second -> Third (입력한 순서대로 출력)
        lMap.forEach((k, v) -> System.out.println(k + " : " + v));
    }
}

TreeMap

  • 키 값을 기준으로 정렬

  • 이진 검색 트리 기반. 정렬이 필요할 때 사용하나 속도는 다소 느림.

  • 예제 코드

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

public class TreeMapEx {
    public static void main(String[] args) {
        // 키 값을 기준으로 오름차순 정렬 (이름순, 숫자순 등)
        Map<Integer, String> tMap = new TreeMap<>();

        tMap.put(300, "C과장");
        tMap.put(100, "A부장");
        tMap.put(200, "B대리");

        // 결과: 100(A부장) -> 200(B대리) -> 300(C과장)
        tMap.forEach((k, v) -> System.out.println(k + " : " + v));
        
        // 유용한 기능: 특정 범위 검색이 가능합니다.
        System.out.println("200번대 이상 사원: " + ((TreeMap<Integer, String>) tMap).tailMap(200));
    }
}

ConcurrentHashMap

  • 멀티스레드 안전

  • 대규모 트래픽 서버 환경에서 데이터가 꼬이지 않게 할 때 필수.

  • 예제 코드

import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;

public class ConcurrentMapEx {
    public static void main(String[] args) {
        // 서버 메모리에 공유되는 캐시나 상태값 저장에 필수
        Map<String, Integer> stockMap = new ConcurrentHashMap<>();

        stockMap.put("iPhone15", 100);

        // 여러 스레드가 동시에 접근해도 안전하게 값을 변경하는 메서드 제공
        stockMap.computeIfPresent("iPhone15", (key, val) -> val - 1);

        System.out.println("안전하게 업데이트된 재고: " + stockMap.get("iPhone15"));
    }
}

적합한 사용 사례

  • 빠른 검색
    • 수만 개의 데이터 중 특정 ID로 정보를 바로 찾아야 하는 경우
  • 데이터 그룹화
    • 부서별 사원 목록, 카테고리별 상품 목록 등 데이터를 특정 기준(Key)으로 묶을 때.
  • 캐싱
    • 무거운 연산 결과를 저장해두고 다시 꺼내 쓸 때

주의사항

  • Thread-Safety

    • 일반적인 HashMap은 여러 스레드가 동시에 접근해 데이터를 수정하면 내부 구조가 깨지거나 무한 루프에 빠질 수 있다.
    • 서버 애플리케이션(Spring Boot 등) 환경에서는 반드시 ConcurrentHashMap을 사용하는 습관을 들이도록 해야한다.
  • Memory Leak (메모리 누수)

    • Map에 데이터를 넣기만 하고 삭제하지 않으면, 서버 메모리는 계속 차오른다.

    • 해결책: 메모리 관리정책

      • 로컬 캐시로 쓸 때는 반드시 Caffeine 같은 라이브러리를 써서 유효 기간을 두거나, 데이터 개수를 제한해야 한다.
  • null 체크

    • Map.get(key)를 호출했을 때 키가 없으면 null이 반환됩니다. 이를 확인하지 않고 바로 메서드를 호출하면NullPointerException(NPE)가 발생한다.
    • 팁: map.getOrDefault(key, "기본값")을 사용하면 안전하다.
  • Initial Capacity (초기 용량 설정)

    • Map은 데이터가 많아지면 내부적으로 저장 공간을 늘리는(Rehash) 작업을 수행하는데, 이게 꽤 무거운 작업이다.
    • 만약 담을 데이터가 대략 100개라는 것을 알고 있다면, new HashMap<>(100) 처럼 초기 크기를 지정해주는 것이 성능 최적화의 기본이다.

0개의 댓글