▩ 목 차 ▩
1. Map이란 ?
1-1. Map을 구현한 주요 클래스들을 살펴보자
1-2. HashMap 클래스에 대해서 자세히 알아보자.
1-2-1. HashMap 객체에 값을 넣고 확인해보자
1-2-2. HashMap 객체의 값을 확인하는 다른 방법들을 알아보자
1-2-3. Map에 어떤 키나 값이 존재하는지를 확인해보자.
1-2-4. Map에서 데이터를 삭제하는 remove()메소드
1-3. 정렬된 키의 목록을 원한다면 TreeMap을 사용하자
1-4. Map을 구현한 Properties 클래스는 알아두면 편리하다.
2. 정리
■ 1. Map이란 ? ■
자바에서의 Map은 우리가 흔히 아는 지도가 아니다.
자바에서의 Map은 키(Key)와 값(Value)으로 이루어져 있다. Map에서 다른 데이터와 구분하기 위한 값의 이름을 키(Key)라고 한다. 그리고 그 키(Key)안에는 값들이 들어있다.
자바의 Map은 키와 값이 1:1로 저장된다. 그런데, 이 키는 해당 Map에서 중복되지 않는다. 만약 키가 다르고, 값이 동일하다면 맵에서 다른 것으로 간주한다.
만약 키가 다르고, 값이 동일하다면 맵에서는 다른 것으로 간주한다.
Map에 대해서 정리해본다면,
- 모든 데이터는 키와 값이 존재한다.
- 키가 없이 값만 저장될 수는 없다.
- 값 없이 키만 저장할 수도 없다.
- 키는 해당 Map에서 고유해야만 한다.
- 값은 Map에서 중복되어서 전혀 상관없다.
Map은 java.util 패키지의 Map이라는 이름의 인터페이스로 선언되어 있고, 구현해 놓은 클래스들도 많이 있다.
간단하게 이 Map 인터페이스에 선언되어 있는 메소드들의 주요 기능을 살펴보자.
Map을 사용할 때 우리가 꼭 기억해야하는 것은,
- Map에 데이터를 넣는 put()
- 데이터를 확인하는 get()
- 데이터를 삭제하는 remove()
■ 1-1. Map을 구현한 주요 클래스들을 살펴보자
Map 인터페이스를 구현한 클래스들은 매우 다양하고 많다. 그 중에서 HashMap, TreeMap, LinkedHashMap 등이 가장 유명하고, 개발자들이 애용하는 클래스다. 그리고 Hashtable이라는 클래스도 있다.
Hashtable 클래스는 Map 인터페이스를 구현하기는 했지만 일반적인 Map 인터페이스를 구현한 클래스들과는 다르다. 아래로 확인하자.
- Map은 컬렉션 뷰(Collection view)를 사용하지만, Hashtable은 Enumeration 객체를 통해서 데이터를 처리한다.
- Map은 키,값, 키-값 쌍으로 데이터를 순환하여 처리할 수 있지만, Hashtable은 이 중에서 키-값 쌍으로 데이터를 순환하여 처리 할 수 없다.
- Map은 이터레이션을 처리하는 도중에 데이터를 삭제하는 안전한 방법을 제공하지만, Hashtable은 그러한 기능을 제공하지 않는다.
==> 다음은 Map인터페이스와 Hashtable 클래스의 차이는 위에 있는 정도다.
HashMap 클래스와 Hashtable 클래스는 다음과 같은 차이가 있다. [ 어떻게 보면 별 게 아닐 수 있지만, 어떻게 보면 중요하다. ]
여기서 중요한점은 어떤 작업을 할 때 어떤 클래스가 더 유리한지를 알고 사용하는 것이다.
즉, Hashtable을 제외한 Map으로 끝나는 클래스들을 여러 쓰레드에서 동시에 접근하여 처리할 필요가 있을 때에는 다음과 같이 선언하여 사용해야만 한다.
Map m = Collections.sychronizedMap(new HashMap(...));
■ 1-2. HashMap 클래스에 대해서 자세히 알아보자.
여러 Map 인터페이스를 구현한 클래스 중에서 가장 많이 사용하는 HashMap 클래스를 자세히 알아보자.
HashMap 클래스는 다음과 같은 상속 관계를 가진다.
HashMap 클래스는 AbstarctMap이라는 abstract 클래스를 확장했으며, 대부분의 주요 메소드는 AbstractMap 클래스가 구현해놓았다. 주요 메소드는 다음절에 알아보고 지금은 어떤 인터페이스를 구현했는지 알아보자.
전에 알아본 셋, 큐와 비교해서 HashMap 클래스에 구현되어 있는 인터페이스들을 보면, 매우 간단하게 되어 있다.
다음으로는 HashMap 클래스의 생성자를 알아보자.
대부분 HashMap 객체를 생성할 때에는 매개변수가 없는 생성자를 이용한다. 하지만 HashMap에 담을 데이터의 개수가 많은 경우에는 초기 크기를 지정해주는 것을 권장한다.
[ HashMap에 저장하는 키가 되는 객체를 직접 만들었을 때에는 HashMap의 키는 기본자료형과 참조자료형 모두 될 수 있다. 그렇기에 보통은 int나 long과 같은 숫자나 String 클래스를 키로 많이 사용한다. ]
어떤 클래스를 만들어 그 클래스를 키로 사용할 때에는 Object 클래스의 hashCode() 메소드와 equals()메소드를 잘 구현해 놓아야만 한다.
[ HashMap에 객체가 들어가면 hashCode() 메소드의 결과 값에 따른 버켓(bucket)이라는 목록(list)형태의 바구니가 만들어진다.
만약 서로 다른 키가 저장되었는데, hashCode() 메소드의 결과가 동일하다면, 이 버켓에 여러개의 값이 들어갈 수 있다. 따라서, get()메소드가 호출되면 hashCode()결과를 확인하고, 버켓에 들어간 목록에 데이터가 여러 개일 경우 equals()메소드를 호출하여 동일한 값을 찾게 된다. 따라서, hashCode()와 equals()메소드를 자동 생성해주는 툴을 이용하는게 편하다. ==> 이해가 잘 안단다... ]
■ 1-2-1. HashMap 객체에 값을 넣고 확인해보자
HashMap에 있는 주요 메소드는 대부분 Map 인터페이스에 정의되어 있다.
[EX] - HashMap 클래스에서 데이터를 넣는 메소드는 put()
package part24;
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");
}
}
위의 코드를 보자.
여기선 선언한 map이라는 HashMap 객체의 키와 값의 타입은 String이다. 그러므로, 이 map에는 다른 타입의 키와 다른 타입의 값을 넣을 수 없다.
map이라는 객체에 put()을 이용하여 키의 값을 "A", 값을 "a"로 할당했다.
[EX] - HashMap 클래스에서 데이터를 넣은것을 get()메소드를 이용하여 값 출력하기
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
위의 코드를 보자.
put을 통해 키-값으로 ("A"-"a")가 있다. 여기서 get()메소드로 키가 "A"인 값을 출력했을 경우에는 값으로 "a"가 나오고 키 가 "B"인 값을 출력했을 경우에는 null이 나온다.
==> 키가 "B"인 값을 출력했을 경우 null이 들어있는 이유는 키가 "B"인 곳에 아무런 값이 안들어 있기 떄문이다. 왜 ArrayIndexOutOfBoundsException 예외가 뜨지 않냐고 말을 하면 HashMap에서는 키나 값에 null을 저장 가능하기 때문이다.
[ 참고로 반면에, Hashtable은 키나 값에 null 저장이 불가능하다. ]
[EX] - HashMap 클래스에서 이미 존재하는 키로 값을 넣기
public void checkHashMap() {
HashMap<String, String> map = new HashMap<String, String>();
map.put("A", "a");
map.put("A","B");
System.out.println(map.get("A"));
System.out.println(map.get("B"));
}
a
null
위의 코드를 실행한 결과를 보면, 이미 존재하는 키로 값을 넣을 때에는 기존의 값을 새로운 값으로 대치한다.
ArrayList 클래스는 추가할 때 add() 메소드, 수정할 때에는 set()메소드를 사용했다.
하지만 HashMap과 같은 Map 관련 클래스에서는 새로운 값을 추가하거나, 기존 값을 수정할 때 모두 put()메소드를 사용한다.
■ 1-2-2. HashMap 객체의 값을 확인하는 다른 방법들을 알아보자
HashMap에 어떤 키가 있는지를 확인하려면 어떻게 해야 할까?
==> keySet()메소드를 사용하면 된다. get()이라는 데이터를 조회하는 메소드를 사용하려면, 어떤 키들이 있는지 확인해야 하므로, Map을 사용할 때 KeySet()메소드는 꼭 알고 있어야 한다.
[ keySet()메소드의 리턴 타입은 Set이다. 그러므로 Set의 제네릭 탑인은 키의 제네릭 타입과 동일하게 지정해주면 된다. ]
[EX] - Map 인터페이스를 구현하 클래스들에서 key의 값을 확인할 수 있는 keySet() 메소드
public void checkKeySet() {
HashMap<String, String> map = new HashMap<String, String>();
map.put("A", "a");
map.put("C", "c"); //1
map.put("D", "d"); //1
Set<String> keySet=map.keySet(); //2
for(String tempKey:keySet) { //3
System.out.println(tempKey+"="+map.get(tempKey)); //4
}
}
A=a
C=c
D=d
위에 코드에서 주석처리된 번호를 보자.
- 조금 더 많은 데이터를 출력하기 위해서 두개의 데이터를 더 추가했다.
- keySet()이라는 Set 타입의 변수를 선언하고, map의 keySet() 메소드 수행 결과를 할당했다.
- for 루프를 사용하여 결과를 출력했다.
- tempkey라는 변수에 할당되는 값들은 HashMap에 담겨있는 키 값이 될 것이므로, 이 키 값 정보를 바탕으로 get()메소드를 사용하여 값을 확인한다.
결과의 순서에 대해서는 Set과 Map은 데이터 추가 순서는 중요치 않다. [ 자바의 자료구조 중 순서가 중요한 것은 List와 Queue 뿐이다. ]
Set은 데이터가 중복되지 않는 것이 중요하고, Map은 키가 중복되지 않는 것이 중요하다.
결론적으로 Map은 데이터를 저장한 순서대로 결과가 출력되지 않는다.
만약 HashMap 객체에 담겨 있는 값만 필요한 경우에는 이렇게 keySet() 메소드를 사용하여 키 목록을 얻어내고, get() 메소드를 사용하여, 하나 하나 받아올 필요는 없다.
==> values()라는 메소드가 있기 때문이다.
[EX] - HashMap 객체에 있는 모든 값을 출력하게 해주는 values() 메소드
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);
}
}
a
c
d
위의 코드를 보자.
values()라는 메소드를 사용하면 HashMap에 담겨있는 값의 목록을 Collection 타입의 목록으로 리턴해준다.
Map에 저장되어 있는 모든 값을 출력할 때에는 values() 메소드를 사용하는 것이 keySet()메소드로 모든 키 값을 가져 온 후 처리하는 것보다 더 간편하다.
그런데 이렇게 데이터를 꺼내는 방법 외에 entrySet()이라는 메소드를 사용할 수도 있다. 이 메소드를 사용하면 Map에 선언된 Entry라는 탑의 객체를 리턴한다. 이 Entry에는 단 하나의 키와 값만이 저장된다. 따라서, getkey()와 getValue()라는 메소드를 사용하면 키와 값을 간단하게 가져올 수 있다.
[EX] - HashMap 객체에서 entrySet()메소드를 이용하여 Set 객체를 리턴하고 그 Set내에는 Map에서 선언된 Entry타입으로 데이터가 저장되어, 이것을 이용하여 getKey(), getValue() 메소드 사용해 모든 데이터 값을 출력하기
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> tempentries : entries) {
System.out.println(tempentries.getKey()+"="+tempentries.getValue());
}
}
A=a
B=b
C=c
D=d
HashMap 클래스를 이용한 객체에서 entrySet()메소드를 사용하면 Set 타입으로 리턴한다. 이 Set 내에는 Map에서 선언된 Entry 타입으로 데이터가 저장된다.
위에 예제들을 보게되면 HashMap 객체의 값을 확인하는 방법들이 많다. 그렇기에 적절히 나에게 맞는 상황에 맞는것을 선택하여 사용하자.
■ 1-2-3. Map에 어떤 키나 값이 존재하는지를 확인해보자.
Map에 어떤 키나 값이 존재하는지를 확인하는 cotainsKey()와 containsValue()메소드가 있다.
[EX] - Map에 어떤 키나 값이 존재하는지를 확인하는 cotainsKey()와 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("B"));
System.out.println(map.containsValue("a"));
System.out.println(map.containsValue("z"));
}
true
true
true
false
위의 코드를 봐보자.
containsKey()메소드는 매개변수로 넘긴 키를 존재하는지를, containsValue()메소드는 매개변수로 넘긴 값이 존재하는지를 리턴해주며 모두 boolean 타입의 결과를 제공한다.
[ 무작정 get() 메소드로 해당 키나 값이 존재하는지 확인하는 것보다는 이렇게 containsKey()나 containsValue()메소드를 사용하는 것이 효과적 ]
■ 1-2-4. Map에서 데이터를 삭제하는 remove()메소드
[EX] - Map에서 데이터를 삭제하는 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
위의 코드를 보자.
"A"를 키로 갖는 데이터가 삭제되었기 때문에 Map의 크기는 0이 된다.
[ Map 인터페이스를 구현한 클래스에서 데이터의 개수를 확인하는 메소드는 size() 메소드 이다. ]
■ 1-3. 정렬된 키의 목록을 원한다면 TreeMap을 사용하자
HashMap 객체의 키를 정렬하려면 Arrays라는 클래스를 사용하면 되지만, 불필요한 객체가 생긴다는 단점이 있다.
==> 이러한 단점을 보완 TreeMap 이라는 클래스가 있다.
TreeMap 클래스는 저장하면서, 키를 정렬한다. 정렬되는 기본적인 순서는 "숫자 > 알파벳 대문자 > 알파벳 소문자 > 한글" 순이다.
이 순서는 String 같은 문자열이 저장되는 순서를 말하는 것이며, 객체가 저장되거나, 숫자가 저장될 때에는 그 순서가 달라진다.
[EX] - HashMap 객체의 키 정렬을 도와주는 TreeMap 클래스
package part24;
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> tempentries : entries) {
System.out.println(tempentries.getKey()+"="+tempentries.getValue());
}
}
}
1=f
A=a
a=g
가=e
위의 코드를 보자.
TreeMap은 키를 정렬하여 저장하고, 키의 목록을 가져와서 출력해 보면 정렬된 순서대로 제공되는 것을 볼 수 있다.
매우 많은 데이터를 TreeMap을 이용하여 보관하여 처리할 때에는 HashMap보다는 느릴 것이다.
==> 키가 정렬되기 때문이다. 하지만 100건, 1000건 정도의 데이터를 처리하고, 정렬을 해야 할 필요가 있다면, HashMap 보다는 TreeMap을 사용하는 것이 더 유리하다.
이렇게 TreeMap이 키를 정렬하는 것은 SortedMap이라는 인터페이스를 구현했기 때문이다.[ SortedMap을 구현한 클래스들은 모두 키가 정렬되어 있어야만 한다. ]
키가 정렬 되었을 때의 장점은, 가장 앞에 잇는 키(firstKey()), 가장 뒤에 있는 키(lastKey()), 특정 키 뒤에 있는 키(higherKey()), 특정 키 앞에 있는 키(lowerKey()) 등을 알 수 있는 메소드를 제공해준다.
==> 이러한 기능들은 키를 검색하는 프로그램을 작성할 때 매우 도움이 된다.
■ 1-4. Map을 구현한 Properties 클래스는 알아두면 편리하다.
Properties 클래스는 Hashtable을 확장(extends)하였다. 따라서, Map 인터페이스에서 제공하는 모든 메소드를 사용할 수 있다. 기본적으로, 자바에서는 시스템의 속성을 이 클래스를 사용하여 제공한다.
우선 시스템의 속성값들을 확인하는 방법을 살펴보자.
[EX]- 시스템의 속성값들을 확인하는 방법( kesSet()메소드를 이용하여 Key를 구하고 이 key를 바탕으로 get()메소드로 값을 구함, 즉, 키와 값 둘 다 출력 가능)
package part24;
import java.util.Collection;
import java.util.Properties;
import java.util.Set;
public class PropertiesSample {
public static void main(String[] args) {
PropertiesSample sample = new PropertiesSample();
sample.checkProperties();
// sample.checkProperties2();
}
public void checkProperties() { // 키를 구해서 get()메소드에 키 값을 이용하여 키와 값 둘 다 출
Properties prop=System.getProperties();
Set<Object> keySet=prop.keySet();
for(Object tempObject : keySet) {
System.out.println(tempObject+"="+prop.get(tempObject));
}
}
// public void checkProperties2() { // 값만 출
// Properties prop=System.getProperties();
//
// Collection<Object> value = prop.values();
// for(Object tempprop:value) {
// System.out.println(tempprop);
// }
// }
}
java.specification.version=17
sun.jnu.encoding=UTF-8
java.vm.vendor=Eclipse Adoptium
sun.arch.data.model=64
java.vendor.url=https://adoptium.net/
java.vm.specification.version=17
os.name=Mac OS X
sun.java.launcher=SUN_STANDARD
user.country=KR
sun.boot.library.path=/Users/minbyeongjun/.p2/pool/plugins/org.eclipse.justj.openjdk.hotspot.jre.full.macosx.aarch64_17.0.1.v20211116-1657/jre/lib
sun.java.command=part24.PropertiesSample
jdk.debug=release
sun.cpu.endian=little
user.home=/Users/minbyeongjun
user.language=ko
java.specification.vendor=Oracle Corporation
java.version.date=2021-10-19
java.vm.compressedOopsMode=Zero based
java.vm.specification.vendor=Oracle Corporation
java.specification.name=Java Platform API Specification
sun.management.compiler=HotSpot 64-Bit Tiered Compilers
java.runtime.version=17.0.1+12
user.name=minbyeongjun
path.separator=:
os.version=12.1
java.runtime.name=OpenJDK Runtime Environment
file.encoding=EUC-KR
java.vm.name=OpenJDK 64-Bit Server VM
java.vendor.version=Temurin-17.0.1+12
java.vendor.url.bug=https://github.com/adoptium/adoptium-support/issues
java.io.tmpdir=/var/folders/lw/q7tjch61247g_yyjtrlvjj400000gn/T/
java.version=17.0.1
user.dir=/Users/minbyeongjun/eclipse-workspace/Java_God_Example
os.arch=aarch64
java.vm.specification.name=Java Virtual Machine Specification
native.encoding=UTF-8
java.vm.info=mixed mode
java.vendor=Eclipse Adoptium
java.vm.version=17.0.1+12
sun.io.unicode.encoding=UnicodeBig
java.class.version=61.0
위 코드의 결과를 보게되면 매우 많은 데이터를 출력하는 것을 볼 수 있다.
Properties 클래스는 Hashtable을 확장한 클래스이기 때문에 키와 값 형태로 저장되어 있다.
시스템에서 제공하는 여러 속성 중에서 개발하면서 많이 사용할 값들은 다음과 같다.
위에 자주 사용한다고 이야기한 속성값들이 대부분 디렉터리나 파일과 관련된 값들이다.
이 값들은 IO 관련 클래스의 상수로 정해져 있다. 가장 좋은 방법은 그 상수들을 사용하는 것이지만, 간단하고 빠르게 시스템의 속성을 확인하려면 예제로 제공한 메소드를 사용하는 것이 간단하다.
왜 Properties 클래스를 사용할까? Hashtable이나 HashMap에 있는 속성을 사용하면 편할텐데..
==> Properties 클래스에서 추가로 제공하는 메소드들을 보면 알 수 있다.
이 외에도 여러가지 메소드가 존재하긴 하지만, Properties 클래스를 이용하는 주된 이유는 위에 있는 메소드들 때문이다.
여기서 comments라고 되어 있는 매개변수들은 저장되는 속성 파일에 주석으로 저장된다.
Properties 클래스의 객체에 시스템 속성만 저장할 수 있는 것은 아니다.
우리가 사용하는 애플리케이션에서 사용할 여러 속성값들을 Properties 클래스를 사용하여 데이터를 넣고, 빼고, 저장하고, 읽어들일 수 있다. 만약 이 클래스가 없다면, 직접 파일을 읽는 메소드를 만들고, 파일에 쓰는 메소드도 만들어야 한다.
[EX] - Properties 클래스를 사용하여 저장과 읽기
public void saveAndLoadProperties() {
try {
String fileName = "text.properties";
File propertiesFile = new File(fileName);
FileOutputStream fos = new FileOutputStream(propertiesFile);
Properties prop = new Properties();
prop.setProperty("writer", "Sangmin, Lee");
prop.setProperty("writerHome", "http://www.GodOfJava.com");
prop.store(fos, "Basic Properties file.");
fos.close();
FileInputStream fis = new FileInputStream(propertiesFile);
Properties propLoaded = new Properties();
propLoaded.load(fis);
fis.close();
System.out.println(propLoaded);
} catch(Exception e) {
e.printStackTrace();
}
}
{writer=Sangmin, Lee, writerHome=http://www.GodOfJava.com}
#Basic Properties file
#Mon Sep 19 00:49:11 KST 2022
writer=Sangmin, Lee
writerHome=http\://www.GodOfJava.com
위의 코드를 보자. [ 첫번째 코드 : 자바 코드 , 2번째 결과 : 자바 실행 결과, 3번째 결과 : 생성된 파일에 작성된 내용 ]
FileOutputStream, FileInputStream, File 이라는 클래스는 처음본다. 간단하게, FileOutputStream은 파일에 저장할 때, FileInputStream는 파일에서 읽을 때, File 클래스는 파일을 다룰 때 사용한다. [ 추후에 배운다. ]
지금은 모르겠지만, 직접 이러한 데이터를 저장하고, 읽는 코드를 작성하려면 여러 줄의 코드를 작성해야만 한다. 하지만, Properties 클래스를 사용하여 저장과 읽기가 한 줄에 끝난다.
자바 소스 코드 실행결과를 보게 되면 중괄호로 묶인 결과가 보이게 되는데, Properties는 Hashtable을 확장(extends)하는데, Hashtable은 toString()메소드가 구현되어 있기 때문에 중괄호로 묶인 것이다.
또한 test.properties파일은 어디에 생겼을까?
==> 기본적으로 시스템 속성 중에서 "user.dir"에 지정되어 있는 경로에 저장된다.
앞으로 개발을 하다 보면 .properties라는 확장자로 끝나는 각종 설정 파일들을 만나게 될 것이다. 이러한 파일들은 지정한 키는 왼쪽에 값은 오른쪽에 표시된다. 그 사이에 등호(=)가 있다. 이 등호로 키와 값을 분리하도록 되어 있다.
그리고 생성된 파일을 열게되면 위의 두 줄이 있다. 어떤 줄이든지, 가장 왼쪽에 #으로 시작하는 줄은 주석으로 간주된다. 마치 자바에서 // 표시를 해놓은 것과 같다. 우리가 store()메소드를 사용할 때 지정한 주석값이 바로 여기에 저장된다.
이번에는 XML로 파일을 저장하고 읽어보자.
[EX] - Properties 클래스를 사용하여 XML로 파일로 저장
public void saveAndLoadPropertiesXML() {
try {
String fileName = "text.xml";
File propertiesFile = new File(fileName);
FileOutputStream fos = new FileOutputStream(propertiesFile);
Properties prop = new Properties();
prop.setProperty("writer", "Sangmin, Lee");
prop.setProperty("writerHome", "http://www.GodOfJava.com");
prop.storeToXML(fos, "Basci XML Propeerty file");
fos.close();
FileInputStream fis = new FileInputStream(propertiesFile);
Properties propLoaded = new Properties();
propLoaded.loadFromXML(fis);
System.out.println(propLoaded);
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
{writer=Sangmin, Lee, writerHome=http://www.GodOfJava.com}
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties> <comment>Basci XML Propeerty file</comment> <entry key="writer">Sangmin, Lee</entry> <entry key="writerHome">http://www.GodOfJava.com</entry> </properties>
위의 코드를 보자. [ 첫번째 코드 : 자바 코드 , 2번째 결과 : 자바 실행 결과, 3번째 결과 : 생성된 파일에 작성된 내용 ]
[EX] - Properties 클래스를 사용하여 저장과 읽기 예제에서 propLoaded.load(fis); --> propLoaded.loadFromXML(fis); 구문으로 변경하였다.
위 코드를 실행하게 되면 생성되는 파일은 "text.xml"이다.
생성된 파일의 내용을 열어 살펴보자.
위에 있는 두 줄은 XML의 규정상 적혀 있기 때문에 신경 쓸 필요 없고 <properties>라는 태그 내에 감싸여 있는 다른 태그들이다. 저장할 때 사용한 주석은 <<comments>>라는 태그 내에 저장된다. 그리고, 각 키와 값으로 선언되어 있는 값들은 <entry>라는 태그 내에 선언되어 있는 것을 볼 수 있다.
위의 두 예제를 보게 되면 Properties 클래스를 사용하면 여러 속성을 저장하고, 읽어 들이는 작업을 보다 쉽게 할 수 있다.
■ 2. 정리 ■
■ collection-Map 인터페이스
Map은 중복되지 않는 키(key)와 그 키와 연결되어 있는 값(value)이 쌍으로 묶여 있는 자료 구조이다.
==> 따라서 Collection 인터페이스를 확장하지 않았다.
Map 인터페이스
- key-value 쌍으로 데이터를 관리한다.
- key는 중복되어서는 안되며, value는 key만 다르다면 중복되어도 상관없다.
- Map은 키로 식별할 수 있는 데이터를 담아두고, 데이터의 위치와 상관 없이 키 만으로 쉽게 꺼낼 필요가 있을 때 용이하다.
- put() : 키와 값으로 데이터를 저장할 때 사용한다.
- get() : 키로 데이터를 꺼낼 때 사용한다.
- Map 인터페이스는 부모 인터페이스가 존재하지 않는다.
- Map 인터페이스를 구현한 클래스로는 AbstractMap, Attributes, AuthProvider, ConcurrentHashMap, LinkedHashMap, PrinterStateReasons, Properties, Provider, RenderingHints, SimpleBindings, TabularDataSupport, TreeMap, UIDefaults, WeakHashMap가 있으며, 이 중에서 HashMap, Hashtable, TreeMap을 많이 사용한다.
'JAVA > 자바의신 2' 카테고리의 다른 글
27장 Serializable과 NIO (1) | 2022.09.21 |
---|---|
25장 쓰레드는 개발자라면 알아두는 것이 좋아요 (0) | 2022.09.19 |
23장 자바랭 다음으로 많이 쓰는 애들은 컬렉션 - Part2(Set과 Queue) (0) | 2022.09.18 |
22장 자바랭 다음으로 많이 쓰는 애들은 컬렉션 - Part1(List) (0) | 2022.09.18 |
21장 실수를 방지하기 위한 제네릭 (0) | 2022.09.17 |