
이 내용은 Backend / Java(Collection Framework) 영역에서 “key–value 구조로 데이터를 매핑”할 때 사용하는 핵심 자료구조다. HashMap은 key는 중복 불가, value는 중복 허용, 그리고 순서가 보장되지 않는다.
key는 중복이 안 되기 때문에 같은 key에 put하면 기존 값이 교체된다. value는 중복이 가능하다.
HashMap<Integer, String> strMap = new HashMap<>();
HashMap<String, String> strMap2 = new HashMap<>();
strMap.put(1, "java");
strMap.put(2, "python");
// key 중복 → value 덮어쓰기
strMap.put(2, "C");
// value 중복 가능
strMap.put(3, "java");
System.out.println(strMap); // {1=java, 2=C, 3=java}
// 순서 없음
strMap2.put("apple", "red");
strMap2.put("banana", "yellow");
strMap2.put("tomato", "red");
System.out.println(strMap2);
System.out.println(strMap2.get("tomato")); // red
System.out.println(strMap2.containsKey("redBanana")); // false
System.out.println(strMap2.containsValue("green")); // false
System.out.println(strMap2.containsValue("red")); // true
Map은 인덱스가 없기 때문에, 보통 keySet()으로 key 집합(Set)을 꺼내 순회하면서 value를 조회한다.
Iterator<String> iterator = strMap2.keySet().iterator();
while (iterator.hasNext()) {
String key = iterator.next();
System.out.println(strMap2.get(key));
}
실무에서는 enhanced for가 더 깔끔하다.
for (String key : strMap2.keySet()) {
System.out.println(strMap2.get(key));
}
이 부분이 실전에서 가장 많이 쓰이는 패턴이다. “여러 개의 데이터 묶음(행, row)을 유연한 구조로 관리”할 때 List<Map> 형태를 자주 사용한다.
코드 구조를 보면, 한 개의 메뉴(menu1, menu2)가 하나의 Map이고, 그 메뉴들을 List로 묶은 형태다.
List<HashMap<String, Object>> menuList = new ArrayList<>();
HashMap<String, Object> menu1 = new HashMap<>();
HashMap<String, Integer> optionMap = new HashMap<>();
optionMap.put("shot", 500);
optionMap.put("cream", 1000);
menu1.put("name", "americano");
menu1.put("money", 2000);
menu1.put("option", optionMap);
HashMap<String, Object> menu2 = new HashMap<>();
HashMap<String, Integer> optionMap2 = new HashMap<>();
optionMap2.put("shot", 500);
optionMap2.put("cream", 1000);
optionMap2.put("syrup", 500);
optionMap2.put("whipping", 1000);
menu2.put("name", "latte");
menu2.put("money", 3000);
menu2.put("option", optionMap2);
menuList.add(menu1);
menuList.add(menu2);
System.out.println(menuList);
이 구조를 테이블 구조로 해석하면 다음과 같다.
즉, 다음과 같은 형태다.
menuList
├─ { name=americano, money=2000, option={shot=500, cream=1000} }
└─ { name=latte, money=3000, option={shot=500, cream=1000, syrup=500, whipping=1000} }
Spring/JDBC, MyBatis, JPA Native Query 등에서 “컬럼이 동적으로 변하거나”, “DTO 만들기 애매할 때” List<Map<String, Object>> 형태로 결과를 받는 경우가 많다.
프론트엔드(HTML/JS) ↔ 백엔드(Spring Boot) ↔ DB 사이에서 JSON과 거의 1:1 구조로 매핑하고 싶을 때 HashMap 구조를 쓴다.
메뉴 옵션처럼 항목 개수가 고정되지 않은 경우, DTO 클래스를 매번 수정하기보다 Map이 더 유연하다.
실무 정석:
HashMap의 key 중복 불가 원리는, 앞에서 배운 HashSet의 “중복 제거 기준(equals/hashCode)”과 완전히 동일하다.
즉, HashMap 내부적으로는 “key들을 Set처럼 관리”한다고 보면 된다.
// 핵심 요약
// HashMap rule: key 중복 불가 (equals() && hashCode() 기준), value 중복 가능
// 실무 패턴: List<Map<String, Object>> = 동적 테이블 / JSON 구조 표현