24장 - 자바랭 다음으로 많이 쓰는 애들은 컬렉션 ― Part3 (Map)
Map
- 모든 데이터는 키와 값이 존재
- 키 없이 값만 저장 불가
- 값 없이 키만 저장 불가
- 키는 해당 Map에서 고유해야
- 값은 Map에서 중복이어도 상관 x
- 자바의 Map은 키와 값이 1:1로 저장됨
Map 인터페이스에 선언된 메서드
리턴 타입 | 메서드 이름 및 매개 변수 | 설명 |
V | put(K key, V value) | 첫 번째 매개 변수인 키를 갖는, 두 번째 매개 변수인 값을 갖는 데이터 저장 |
void | putAll(Map<? extends K, ? extends V> m) | 매개 변수로 넘어온 Map의 모든 데이터 저장 |
V | get(Object key) | 매개 변수로 넘어온 키에 해당하는 값 넘겨줌 |
V | remove(Object key) | 매개 변수로 넘어온 키에 해당하는 값 넘겨주며, 해당 키와 값은 Map에서 삭제 |
Set<K> | keySet() | 키의 목록을 Set 타입으로 리턴 |
Collection<V> | values() | 값의 목록을 Collection 타입으로 리턴 |
Set<Map.Entry<K,V>> | entrySet() | Map 안에 Entry라는 타입의 Set 리턴 |
int | size() | Map 크기 리턴 |
void | clear() | Map 내용 삭제 |
Map의 핵심 메서드
put() | get() | remove() |
Map에 데이터 넣음 | 데이터 확인 | 데이터 삭제 |
Map 구현한 주요 클래스
Map 인터페이스 | Hashtable 클래스 |
컬렉션 뷰(Collection view) 통해 데이터 처리 키-값 쌍으로 데이터 순환하여 처리 가능 이터레이션 처리 도중 데이터 삭제하는 안전한 방법 제공 |
Map 인터페이스 구현함 Enumeration 객체 통해 데이터 처리 키-값 쌍으로 데이터 순환하여 처리 불가 이터레이션 처리 도중 안전한 데이터 삭제 기능 제공 x |
HashMap vs Hashtable
기능 | HashMap | Hashtable |
키나 값에 null 저장 가능 여부 | 가능 | 불가능 |
여러 쓰레드 안전 여부 | 불가능 | 가능 |
Map - Thread safe
- Hashtable 제외한 Map으로 끝나는 클래스들을 여러 쓰레드에서 동시에 접근해 처리하려면
Map m = Collections.synchronizedMap(new HashMap(...));
Hashtable, Vector | 그 외 대부분 Collection 관련 클래스 |
클래드가 쓰레드에 안전하게 개발됨 | 위와 같이 처리하거나 이름에 Concurrent 포함돼야 쓰레드에 안전하게 사용 가능 ex) ConcurrentHashMap, CopyOnWriteArrayList |
HashMap 상속 관계
java.lang.Object
java.util.AbstractMap<K,V>
java.util.HashMap<K,V>
HashMap이 구현한 인터페이스
인터페이스 | 용도 |
Serializable | 원격으로 객체 전송 및 파일에 저장할 수 있음을 지정 |
Cloneable | Object 클래스의 clone() 메서드가 제대로 수행될 수 있음을 지정 = 복제 가능한 객체임을 의미 |
Map<E> | Map의 기본 메서드 지정 |
HashMap 클래스의 객체 생성 위한 생성자
생성자 | 설명 |
HashMap() | 16개의 저장 공간 갖는 HashMap 객체 생성 |
HashMap(int initialCapacity) | 매개 변수만큼의 저장 공간 갖는 HashMap 객체 생성 |
HashMap(int initialCapacity, float loadFactor) | 첫 매개 변수의 저장 공간을 갖고, 두 번째 매개 변수의 로드 팩터를 갖는 HashMap 객체 생성 |
HashMap(Map<? extends K, ? extends V> m) | 매개 변수로 넘어온 Map 구현한 객체에 있는 데이터를 갖는 HashMap 객체 생성 |
- HashMap에 담을 데이터 개수 많을 땐 초기 크기 정해주는 게 좋음
- HashMap의 키
- 기본 자료형과 참조 자료형 모두 가능
- But 직접 임의 클래스 만들어 이를 키로 사용할 땐 Object 클래스의 hashCode()와 equals() 잘 구현해야함
- HashMap에 객체 들어가면 hashCode() 결과값에 따른 버켓(bucket)이라는 목록(list) 형태의 바구니 만들어짐
- 만약 서로 다른 키가 저장됐는데 hashCode() 결과가 동일하면, 이 버켓에는 여러 개의 값 들어갈 수 있음
- ➡ get() 호출 시 hashCode() 결과 확인 + 버켓에 들어간 목록에 데이터가 여러 개일 때 equals()로 동일한 값 찾게 됨
- ➡ 키가 되는 객체 직접 작성 시, 개발툴에서 제공하는 hashCode()와 equals() 자동 생성해주는 기능 사용해 해당 메서드 꼭 구현해야
HashMap 객체에 값 넣고 확인하기
Collection | Map |
add(): 데이터 추가 | put(): 데이터 넣기 |
package d.collection;
import java.util.HashMap;
public class MapSample {
public static void main(String[] args) {
MapSample sample = new MapSample();
sample.checkHashMap();
}
public void checkHashMap() {
HashMap<String, String> map = new HashMap<String, String>();
map.put("A", "a");
System.out.println(map.get("A"));
System.out.println(map.get("B"));
}
}
//결과
//a
//null
Collection | Map |
map.get("B")처럼 해당 위치에 값이 없을 때, Collection은 ArrayIndexOutOfBoundsException 발생 해당 위치가 존재하지 않을 때 개발자에게 알려줘야 하기에 예외 발생 |
Collection과 달리, Map에서는 존재하지 않는 키로 get()하면 null 리턴 |
ArrayList vs HashMap
ArrayList | HashMap |
추가 : add() 수정 : set() |
추가 & 수정 : put() 이미 존재하는 키로 값 넣을 때, 기존의 값을 새로운 값으로 대치 |
HashMap 객체의 값 확인하는 다른 방법
- keySet()
import java.util.Set;
public void checkKeySet() {
HashMap<String, String> map = new HashMap<String, String>();
map.put("A", "a");
map.put("C", "c");
map.put("D", "d");
Set<String> keySet = map.keySet();
for(String tempKey : keySet) {
System.out.println(tempKey + " = " + map.get(tempKey));
}
}
//결과
//D = d
//A = a
//C = c
자바의 자료 구조에서 저장 순서 보장되는 항목은?
저장 순서 중요한 것 | 저장 순서 중요 x ➡ 데이터 저장순으로 결과 출력 x | |
List, Queue | Set: 데이터 중복 x | Map: 키 중복 x |
- values()
- HashMap 객체에 담긴 값만 필요할 때
import java.util.Collection;
public void checkValues() {
HashMap<String, String> map = new HashMap<String, String>();
map.put("A", "a");
map.put("C", "c");
map.put("D", "d");
Collection<String> values = map.values();
for(String tempValue : values) {
System.out.println(tempValue);
}
}
//결과
//d
//a
//c
- Map에 저장된 모든 '값' 출력 시 values() 사용하는 게 keySet()으로 모든 키-값 가져오는 것보다 간편
- entrySet()
- Map에 선언된 Entry라는 타입의 객체 리턴
- Entry에는 단 하나의 키-값만 저장됨
import java.util.Map.Entry;
import java.util.Set;
public void checkHashMapEntry() {
HashMap<String, String> map = new HashMap<String, String>();
map.put("A", "a");
map.put("B", "b");
map.put("C", "c");
map.put("D", "d");
Set<Map.Entry<String, String>> entries = map.entrySet();
for(Map.Entry<String, String> tempEntry : entries) {
System.out.println(tempEntry.getKey() + " = " + tempEntry.getValue());
}
}
//결과
//D = d
//A = a
//B = b
//C = c
- containsKey() & containsValue()
public void checkContains() {
HashMap<String, String> map = new HashMap<String, String>();
map.put("A", "a");
map.put("B", "b");
map.put("C", "c");
map.put("D", "d");
System.out.println(map.containsKey("A"));
System.out.println(map.containsKey("Z"));
System.out.println(map.containsValue("a"));
System.out.println(map.containsValue("z"));
}
//결과
//true
//false
//true
//flase
- remove()
public void checkRemove() {
HashMap<String, String> map = new HashMap<String, String>();
map.put("A", "a");
map.remove("A");
System.out.println(map.size());
}
//결과
//0
TreeMap
HashMap | TreeMap |
객체의 키 정렬하려면 Arrays 클래스 사용, but 불필요한 객체 생김 | HashMap에서의 단점 보완 저장하면서 키 정렬 정렬 순서 : 숫자 > 알파벳 대문자 > 알파벳 소문자 > 한글 (String 같은 문자열 저장 순서) (객체 및 숫자 저장 시 순서 달라짐) |
package d.collection;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class TreeMapSample {
public static void main(String[] args) {
TreeMapSample sample = new TreeMapSample();
sample.checkTreeMap();
}
public void checkTreeMap() {
TreeMap<String, String> map = new TreeMap<String, String>();
map.put("A", "a");
map.put("가", "e");
map.put("1", "f");
map.put("a", "g");
Set<Map.Entry<String, String>> entries = map.entrySet();
for(Map.Entry<String, String> tempEntry : entries) {
System.out.println(tempEntry.getKey() + " = " + tempEntry.getValue());
}
}
}
//결과
//1 = f
//A = a
//a = g
//가 = e
TreeMap 특징
- 키를 정렬하여 저장
- 키의 목록 가져와 출력 시 정렬된 순서대로 제공됨
- 키가 정렬되기에 데이터가 많을 때 HashMap보다 느림
- SortedMap 인터페이스 구현했기에 키 정렬 가능
- 키 정렬 시, 가장 앞에 있는 키(firstKey()), 가장 뒤에 있는 키(lastKey()), 특정 키 뒤에 있는 키(higherKey()), 특정 키 앞에 있는 키(lowerKey()) 등 알 수 있는 메서드 제공
Map 구현한 Properties 클래스
- Hashtable 확장함 ➡ Map 인터페이스의 모든 메서드 사용 가능
package d.collection;
import java.util.Properties;
import java.util.Set;
public class PropertiesSample {
public static void main(String[] args) {
PropertiesSample sample = new PropertiesSample();
sample.checkProperties();
}
public void checkProperties() {
Properties prop = System.getProperties();
Set<Object> keySet = prop.keySet();
for(Object tempObject : keySet) {
System.out.println(tempObject + " = " + prop.get(tempObject));
}
}
}
- System 클래스에 staic으로 선언되어 있는 getProperties() 호출 시, Properties 타입의 객체 리턴
System에서 제공하는 Properties 중 자주 사용할 값 목록
속성 | 설명 |
user.language | 사용자의 사용 언어 |
user.dir | 현재 사용 중인 기본 디렉터리 |
user.home | 사용자 계정의 홈 디렉터리 |
java.io.tmpdir | 자바에서 사용하는 임시 디렉터리 |
file.encoding | 파일의 기본 인코딩 |
sun.io.unicode.encoding | 유니코드 인코딩 |
path.separator | 경로 구분자 |
file.separator | 파일 구분자 |
line.separator | 줄(line) 구분자 |
- 위 값들 중 대부분은 IO 클래스의 상수로 정해져있음
Properties 클래스가 추가 제공하는 메서드
리턴 타입 | 메서드 이름 및 매개 변수 | 설명 |
void | load(InputStream inStream) | 파일에서 속성 읽음 |
void | load(Reader reader) | |
void | loadFromXML(InputStream in) | XML로 된 속성 읽음 |
void | store(OutputStream out, String comments) | 파일에 속성 저장 |
void | store(Writer writer, String comments) | |
void | storeToXML(OutputStream os, String comment) | XML로 구성되는 속성 파일 생성 |
void | storeToXML(OutputStream os, String comment, String encoding) |
- 여기서의 comments : 저장되는 속성 파일에 주석으로 저장됨
XML
- eXtensible Markup Language
- HTML도 XML의 일종
- 태그로 구성된 텍스트 문서를 의미
- XML은 서로 데이터 주고 받을 때 표준 정하기 쉬움
- ex1) 이런 서비스는 어떤 데이터를 정해져 있는 XML 형태로 요청 시, 정해져 있는 형태의 XML로 데이터를 받을 수 있는 기능 제공(요즘은 json 타입 많이 사용)
- ex2) HTML도 정해져 있는 형태로 파일 만들어 놓으면 IE, 크롬, 사파리 등 브라우저에서 데이터 읽어서(parsing) 화면 구성할 수 있도록 정해놓음
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public void saveAndLoadProperties() {
try {
String fileName = "test.properties";
//파일 다룰 때
File propertiesFile = new File(fileName);
//파일 저장
FileOutputStream fos = new FileOutputStream(propertiesFile);
Properties prop = new Properties();
prop.setProperty("Writer", "Adrian, Black";
prop.setProperty("WriterHome", "http://www.test.com");
prop.store(fos, "Basic Properties file");
fos.close();
//파일 읽기
FileInputStream fis = new FileInputStream(propertiesFile);
Properties propLoaded = new Properties();
propLoaded.load(fis);
System.out.println(propLoaded);
fis.close();
} catch(Exception e) {
e.printStackTrace();
}
}
//결과
//{WriterHome=http://www.test.com, Writer=Adrian, Black}
- Hashtable에 toString() 구현되어 있기에 Properties 출력하면 중괄호로 묶임
test.properties 파일 저장 위치 : 기본적으로 "user.dir"에 지정된 경로에 저장됨 - test.properties로 살펴보는 .properties 파일의 기본 구성
#Basic Properties file
#Wed XXX XX 09:40:31 KST 201X
WriterHome=http\://www.test.com
Writer=Adrian, Black
- 키=값으로 구성
- #: 주석
- 주석 부분 : store() 사용 시 지정한 주석값
- 주석 이후 해당 파일 생성 날짜가 자동으로 찍힘
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public void saveAndLoadPropertiesXML() {
try {
String fileName = "test.xml";
File propertiesFile = new File(fileName);
FileOutputStream fos = new FileOutputStream(propertiesFile);
Properties prop = new Properties();
prop.setProperty("Writer", "Adrian, Black";
prop.setProperty("WriterHome", "http://www.test.com");
prop.store(fos, "Basic XML Property file");
fos.close();
FileInputStream fis = new FileInputStream(propertiesFile);
Properties propLoaded = new Properties();
propLoaded.load(fis);
System.out.println(propLoaded);
fis.close();
} catch(Exception e) {
e.printStackTrace();
}
}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>Basic XML Property file</comment>
<entry key="WriterHome">http://www.test.com</entry>
<entry key="Writer">Adrian, Black</entry>
</properties>
자바의 자료구조 종합 정리
'Backend > Java' 카테고리의 다른 글
[자바의 신] 26장 (ongoing) (0) | 2022.08.18 |
---|---|
[자바의 신] 25장 (ongoing) (0) | 2022.08.18 |
[자바의 신] 23장 (0) | 2022.08.09 |
[자바의 신] 22장 (0) | 2022.08.09 |
[자바의 신] 21장 (0) | 2022.08.09 |
댓글