일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- mssql
- 명령어
- IntelliJ
- mysql
- group by
- 리눅스
- spring
- oracle
- java
- 호이스팅
- Linux
- 추상클래스
- Javascript
- github
- MongoDB
- JPA
- PostgreSQL
- Python
- SQL
- analytics4
- 트랜잭션
- docker
- MariaDB
- 자바
- 티스토리챌린지
- rsync
- 오블완
- git
- pandas
- DBMS
- Today
- Total
hanker
Java - Collection Framework의 꽃 Map 사용법 및 활용법 본문
Java의 Map 인터페이스는 데이터를 키-값 쌍으로 저장하는 자료구조로, 단순한 put/get 외에도 다양한 기능을 제공한다.
이번 글에서는 다양한 활용방법과 동작 방법에 대해서 알아보자.
1. Map 이란
1-1. Map 개념
Map은 각 데이터가 고유한 키와 그에 대응하는 값으로 구성된다.
한 키에는 하나의 값만 매핑된다.
예를 들어, {"apple" : 1, "banana": 2} 와 같이 구성된다.
- 키는 중복될 수 없다.
- 값은 중복될 수 있다.
1-2. 구현체 종류
Java에서는 여러 Map 구현체를 제공한다.
- HashMap : 해시 테이블을 기반으로 하며, 순서 보장이 없다.
- TreeMap : 키를 정렬된 순서에 따라 저장한다.
- LinkedHashMap : 삽입 순서 또는 접근 순서를 유지한다.
- ConcurrentHashMap : 멀티스레드 환경에서 안전하게 사용할 수 있다.
2. 기본 메서드
Map 인터페이스는 데이터를 추가, 조회, 삭제하기 위한 기본 메서드를 제공한다.
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
// 1. Map 생성 및 데이터 추가 (put)
Map<String, Integer> map = new HashMap<>();
map.put("apple", 10);
map.put("banana", 20);
map.put("cherry", 30);
System.out.println("초기 Map: " + map); // 예: {apple=10, banana=20, cherry=30}
// 2. 값 조회 (get)
// "apple" 키에 해당하는 값을 반환
Integer appleCount = map.get("apple");
System.out.println("apple의 값: " + appleCount); // 출력: 10
// 3. 키 존재 여부 확인 (containsKey)
if (map.containsKey("banana")) {
System.out.println("Map에 'banana' 키가 존재합니다.");
}
// 4. 값 존재 여부 확인 (containsValue)
if (map.containsValue(30)) {
System.out.println("Map에 값 30이 존재합니다.");
}
// 5. 엔트리 삭제 (remove)
// "cherry" 키에 해당하는 엔트리를 제거
map.remove("cherry");
System.out.println("cherry 제거 후 Map: " + map); // 예: {apple=10, banana=20}
// 6. keySet(), values(), entrySet() 사용
// 모든 키를 반환
System.out.println("모든 키: " + map.keySet()); // 예: [apple, banana]
// 모든 값을 반환
System.out.println("모든 값: " + map.values()); // 예: [10, 20]
// 모든 키-값 쌍을 엔트리 형태로 반환
System.out.println("모든 엔트리: " + map.entrySet()); // 예: [apple=10, banana=20]
}
}
- put : 키와 값을 추가한다. 중복 X
- get : 키에 해당하는 값을 반환하며, 키가 없으면 null을 반환한다.
- remove : 해당 키의 엔트리를 삭제한다.
- containsKey / containsValue : 특정 키 또는 특정 값의 존재 여부를 확인한다.
- keySet / values / entrySet : Map에 저장된 모든키, 값 또는 키-값 쌍을 각각의 컬렉션으로 반환한다.
3. Java 8 이후 추가된 고급 기능과 예제
Java 8 부터 람다 표현식을 활용해 Map을 더욱 효율적으로 다룰 수 있도록 여러 메서드가 추가되었다.
3-1. putIfAbsent
지정한 키가 없을 경우에만 값을 넣어준다. (중복 확인)
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
// "apple" 키가 이미 존재하므로 값은 변경되지 않음
map.putIfAbsent("apple", 2);
System.out.println("apple: " + map.get("apple")); // 출력: 1
}
}
3-2. compute
키의 존재 여부와 상관없이 람다식을 통해 값을 계산하여 저장한다.
예를 들어, 기존 값에 10을 더하거나, 값이 없으면 초기값을 할당한다.
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
// 기존 값 1에 10을 더해서 업데이트
map.compute("apple", (key, val) -> (val == null) ? 1 : val + 10);
System.out.println("apple after compute: " + map.get("apple")); // 출력: 11
// "banana"는 키가 없으므로 20을 할당
map.compute("banana", (key, val) -> (val == null) ? 20 : val + 10);
System.out.println("banana: " + map.get("banana")); // 출력: 20
}
}
3-3. computeIfAbsent
키가 존재하지 않을 대에만 람다식을 통해 값을 계산하고 추가한다.
주로 캐싱(lazy initialization)에 활용된다.
import java.util.HashMap;
import java.util.Map;
public class CachingExample {
public static void main(String[] args) {
Map<Integer, String> cache = new HashMap<>();
// 키 1에 해당하는 데이터가 없을 때만 람다식 실행
String data = cache.computeIfAbsent(1, id -> {
System.out.println("데이터 생성 중...");
return "데이터 for id " + id;
});
System.out.println(data);
// 이미 캐싱되어 있으므로, 람다식이 다시 실행되지 않음
String cachedData = cache.computeIfAbsent(1, id -> {
System.out.println("이 메시지는 출력되지 않습니다.");
return "새로운 데이터";
});
System.out.println(cachedData);
}
}
3-4. computeIfPresent
키가 존재할 때만 값을 업데이트한다.
특정 조건을 만족하는 경우에만 값 변경을 할 경우 유용하다.
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Map<String, Integer> inventory = new HashMap<>();
inventory.put("apple", 10);
inventory.put("banana", 5);
// "apple" 키가 존재할 때만 재고를 2배로 증가
inventory.computeIfPresent("apple", (key, val) -> val * 2);
// "orange" 키는 없으므로 아무 변화 없음
inventory.computeIfPresent("orange", (key, val) -> val * 2);
inventory.forEach((key, value) ->
System.out.println(key + " 재고: " + value)
);
}
}
3-5. merge
키가 없으면 주어진 값을 저장하고, 키가 있으면 기존 값과 새 값을 결합(merge)하는 방식으로 처리한다.
예를 들어, 단어 빈도수 카운팅이나 누적 합계를 구할 때 유용하다.
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
String[] words = {"apple", "banana", "apple", "orange", "banana", "apple"};
Map<String, Integer> wordCount = new HashMap<>();
for (String word : words) {
// 키가 없으면 1을, 있으면 기존 값에 1을 더함
wordCount.merge(word, 1, Integer::sum);
}
wordCount.forEach((key, count) ->
System.out.println(key + " : " + count)
);
}
}
정리
Map 인터페이스는 기본 메서드와 추가된 고급 메서드를 통해 단순한 데이터 추가 및 삭제와 복잡한 로직을 간결하게 처리할 수 있다.
각 메서드를 적절히 활용하면 코드의 가독성과 유지보수성이 크게 향상된다.
끝.
'JAVA' 카테고리의 다른 글
Java - Custom Annotation 만들기 (기본 개념과 구현 방법) (0) | 2025.02.25 |
---|---|
Java - Enum 클래스 사용법 (0) | 2025.02.22 |
Java - Set 사용 법 (HashSet, TreeSet, LinkedHashSet) (0) | 2025.02.15 |
Java - List 인터페이스 (ArrayList, LinkedList, Vector 등) (1) | 2025.02.12 |
Java - 예외 처리의 활용 및 효율적인 관리 방법 (Custom Exception, Exception Propagation) (0) | 2025.02.10 |