-
[Java] 컬렉션 Map 계열IT/개발(자바, 서블릿, 스프링 등) 2020. 1. 28. 02:14
Map 계열
List의 특징은 데이터가 추가되는 순서대로 메모리에 저장되며 저장될 때마다 인덱스 또는 위치 정보가 부여되어 저장된 데이터들의 순서를 알 수 있다. 그런데 Map은 위치 정보(인덱스나 다른 데이터의주소)를 가지지 않는다는 것은 데이터들이 저장된 순서를 보장하지 않는다는 의미다. 데이터가 Key와 Value로 구성되어 있다. Key 값은 데이터에 접근할 때 사용하는 정보다.
Map의 장점은 데이터의 검색 속도가 빠르다. 키를 사용하여 데이터를 처리하므로 중복된 키가 존재할 수 없다. API 문서의 리턴 타입과 매개변수에 사용된 K와 V는 Map 생성 시 제네릭으로 선언된 키의 타입과 밸류 타입을 의미한다.
Entry 인터페이스
Entry는 Map 인터페이스에 선언된 내부 인터페이스다. 내부 클래스나 내부 인터페이스는 외부객체명.내부객체명으로 표현한다. 따라서 Map 인터페이스의 내부 인터페이스로 선언된 Entry는 Map.Entry로 표현해야 한다. Entry는 Map에 저장되는 데이터 단위인 키와 밸류를 가지는 객체다. Map은 여러 개의 Entry로 구성된 컬렉션이다.
HashMap 클래스
HashMap은 Map 인터페이스를 구현하고 있다. HashMap은 Map 인터페이스를 구현하고 있다. HashMap은 해싱(hashing)이란 검색 방법을 사용하기 때문에 많은 양의 데이터를 검색할 때 효율적이다.해싱이란 메모리에 저장된 데이터를 빨리 찾을 수 있도록 주소에 직접 접근할 수 있는 짧은 길이의 값이나 키로 변환하는 것이다.
생성자
HashMap 클래스의 생성자는 키와 밸류가 함께 저장되는 구조이므로 생성할 때 키 타입과 밸류 타입을 지정해야 한다. 자바 API 문서에서 HashMap 생성자에 대한 설명을 보면, '초기 용량(capacity) 16, 사용률(load factor) 0.75로 지정된 비어 있는 HashMap을 생성하는 생성자'라고 되어 있다. 여기에서 용량과 사용률은 무엇일까?
용량(capacity)
HashMap의 용량이라는 것은 캐비닛에서 서랍의 개수라고 생각할 수 있다. 16개의 비어 있는 캐비닛을 생성한다. 캐비닛에 보관하는 자료는 서랍이 몇 개냐에 따라 자료를 찾는 속도가 달라진다. 보관하는 자료가 120개가 있다고 가정하자. 서랍이 한 개라면 120개의 자료를 한 서랍에 모두 보관해야 하고 자료를 찾을 때 120개의 중 하나를 선택한다. 서랍이 4개라면 자료를 4개로 분류하여 자료와 관련 있는 서랍을 선택한 후에 30개 중 하나를 선택하면 된다. 여러 개의 서랍을 가진 캐비닛을 사용하면 원하는 자료를 빨리 찾을 수 있는 장점이 있다. 기본 용량을 변경할 수도 있다.
사용률(load factor)
HashMap의 용량을 변경할 조건을 의미한다. 전체 용량에서 데이터가 75% 저장되면 현재 용량의 2배 정도로 용량이 변경된다.
import java.util.HashMap; public class HashMapTest { public static void main(String[] args) { String word[] = {"BUMBLEBEE", "HEAVEN", "ALTHOUGH", "WONDER"}; String meaning[] = {"꿀벌과에 속하는 호박벌", "천국", "그럼에도 불구하고", "호기심이 들다"}; HashMap<String, String> dic = new HashMap<>(); for (int i = 0; i < word.length; i++) { dic.put(word[i], meaning[i]); } System.out.println(dic); //{HEAVEN=천국, BUMBLEBEE=꿀벌과에 속하는 호박벌, WONDER=호기심이 들다, ALTHOUGH=그럼에도 불구하고} System.out.println(dic.size()); //4 System.out.println(dic.keySet()); //[HEAVEN, BUMBLEBEE, WONDER, ALTHOUGH] System.out.println(dic.values()); //[천국, 꿀벌과에 속하는 호박벌, 호기심이 들다, 그럼에도 불구하고] System.out.println("HEAVEN : " + dic.get("HEAVEN")); //HEAVEN : 천국 dic.replace("HEAVEN", "아주 행복한 감정"); System.out.println("HEAVEN : " + dic.get("HEAVEN")); //HEAVEN : 아주 행복한 감정 dic.put("HEAVEN", "이상적인 세상"); System.out.println("HEAVEN : " + dic.get("HEAVEN")); //HEAVEN : 이상적인 세상 System.out.println(dic.containsKey("BUMBLEBEE")); //true System.out.println(dic.containsValue("자장가")); //false dic.remove("HEAVEN"); System.out.println(dic.containsKey("HEAVEN")); //false dic.clear(); System.out.println(dic.isEmpty()); //true System.out.println(dic.size()); //0 } }
아래의 예제는 HashMap에 저장된 모든 데이터에 접근하는 여러 가지 방법을 사용하고 있다.
import java.util.HashMap; import java.util.Iterator; import java.util.Map; public class HashMapTest02 { public static void main(String[] args) { HashMap<String, String> dic = new HashMap<>(); dic.put("고진감래", "고생 끝에 즐거움이 옴"); dic.put("분골쇄신", "몸이 부서질정도로 노력을 다함"); dic.put("권토중래", "실패를 발판삼아 재기함"); dic.put("교학상자", "가르치고 배우면서 서로 성장함"); dic.put(null, null); //HashMap은 null 값 저장 가능 // 방법 1 Iterator<String> keys = dic.keySet().iterator(); while(keys.hasNext()){ String key = keys.next(); System.out.println(String.format("%s : %s", key, dic.get(key))); } // 방법 2 for (Map.Entry<String, String> elem : dic.entrySet()) { System.out.println(String.format("%s : %s", elem.getKey(), elem.getValue())); } // 방법 3 for (String key : dic.keySet()) { System.out.println(String.format("%s : %s", key, dic.get(key))); } } } [실행결과] null : null 권토중래 : 실패를 발판삼아 재기함 분골쇄신 : 몸이 부서질정도로 노력을 다함 교학상자 : 가르치고 배우면서 서로 성장함 고진감래 : 고생 끝에 즐거움이 옴 null : null 권토중래 : 실패를 발판삼아 재기함 분골쇄신 : 몸이 부서질정도로 노력을 다함 교학상자 : 가르치고 배우면서 서로 성장함 고진감래 : 고생 끝에 즐거움이 옴 null : null 권토중래 : 실패를 발판삼아 재기함 분골쇄신 : 몸이 부서질정도로 노력을 다함 교학상자 : 가르치고 배우면서 서로 성장함 고진감래 : 고생 끝에 즐거움이 옴
'IT > 개발(자바, 서블릿, 스프링 등)' 카테고리의 다른 글
[Java] 입출력 개요 (0) 2020.01.29 [Java] 컬렉션 Set 계열 (0) 2020.01.28 [Java] 컬렉션 개요 (0) 2020.01.27 [Java] 어노테이션 (0) 2020.01.25 [Java] 제네릭 개념 정리 (0) 2020.01.24