본문 바로가기
Back-end

11 컬렉션 프레임웍(6)

by 신재권 2021. 7. 10.

TreeMap

TreeMap은 이름에서 알 수 있듯이 이진검색트리의 형태로 키와 값의 쌍으로 이루어진 데이터를 저장한다. 그래서 검색과 정렬에 적합한 컬렉션 클래스이다.

HashMap과 TreeMap의 검색은 대부분의 경우에서 HashMap이 TreeMap보다 더 뛰어나므로 HashMap을 사용하는 것이 좋다. 다만 범위 검색이나 정렬이 필요한 경우에는 TreeMap을 사용하자


TreeMap의 생성자와 메서드


TreeMap() : TreeMap객체를 생성


TreeMap(Comparator c) : 지정된 Comparator를 기준으로 정렬하는 TreeMap객체를 생성


TreeMap(Map m) : 주어진 Map에 저장된 모든 요소를 포함하는 TreeMap을 생성


TreeMap(SortedMap m) : 주어진 SortedMap에 저장된 모든 요소를 포함하는 TreeMap을 생성


Map.Entry ceilingEntry(Object key) : 지정된 key와 일치하거나 큰 것중 제일 작은 것의 키와 값의 쌍(Map.Entry)를 반환. 없으면 null반환


Object ceilingKey(Object key) : 지정된 key와 일치하거나 큰 것 중 제일 작은 것의 키를 반환, 없으면 null반환


void clear() : TreeMap에 저장된 모든 객체를 제거


Object clone() : 현재 TreeMap을 복제해서 반환


Comparator comparator() : TreeMap의 정렬 기준이 되는 Compartor를 반환, Compartor가 지정되지 않았다면 null을 반환


boolean containsKey(Object key) : TreeMap에 지정된 키(key)가 포함되어 있는지 알려줌(포함되어 있으면 true)


boolean containsValue(Object value) : TreeMap에 지정된 값(value)가 포함되어 있는지 알려줌(포함되어 있으면 true)


NavigableSet desecendingKeySet() : TreeMap에 저장된 키를 역순으로 정렬해서 NavigableSet에 담아서 반환


Set entrySet() : TreeMap에 저장된 키와 값을 엔트리(키와 값의 결합)의 형태로 Set에 저장해서 반환


Map.Entry firstEntry() : TreeMap에 저장된 첫번째(가장 작은)키와 값의 쌍(Map.Entry)을 반환


Object firstKey() : TreeMap에 저장된 첫번째(가장 작은) 키를 반환


Map.Entry floorEntry(Objec tkey) : 지정된 key와 일치하거나 작은 것 중에서 제일 큰 키의 쌍(Map.Entry)을 반환, 없으면 null을 반환


Object floorKey(Object key) : 지정된 key와 일치하거나 작은 것 중에서 제일 큰 키를 반환, 없으면 null을 반환


Object get(Object key) :지정된 키(key)의 값(객체)을 반환


SortedMap headMap(Object toKey) : TreeMap에 저장된 첫번째 요소부터 지정된 범위에 속한 모든 요소가 담긴 SortedMap을 반환(toKey는 미포함)


NavigableMap headMap(Object toKey, boolean inclusive) : TreeMap에 저장된 첫번째 요소부터 지정된 범위에 속한 모든 요소가 담긴 SortedMap을 반환, inclusive의 값이 true이면 toKey도 포함)


Map.Entry higherEntry(Object key) : 지정된 key보다 큰 키 중에서 제일 작은 키의 쌍(Map.Entry)를 반환, 없으면 null을 반환


boolean isEmpty() : TreeMap이 비어있는지 알려준다.


Set keySet() : TreeMap에 저장된 모든 키가 저장된 Set을 반환


Map.Entry lastEntry() : TreeMap에 저장된 모든 키가 저장된 Set을 반환


Map.Entry lowerEntry(Object key) : 지정된 key보다 작은 키 중에서 제일 큰 키의 쌍(Map.Entry)을 반환, 없으면 null을 반환


Object lowerKey(Object key) : 지정된 key보다 작은 키 중에서 제일 큰 키의 쌍(Map.Entry)을 반환, 없으면 null을 반환


NavigableSet naviableKeySet() : TreeMap의 모든 키가 담긴 NaviableSet을 반환


Map.Entry pollFirstEntry() : TreeMap에서 제일 작은 키를 제거하면서 반환


Map.Entry pollLastEntry() : TreeMap에서 제일 큰 기를 제거하면서 반환


Object put(Object key, Object value) :지정된 키와 값을 TreeMap에 저장


void putAll(Map map) : Map에 저장된 모든 요소를 TreeMap에 저장


Object remove(Object key) : TreeMap에 지정된 키로 저장된 값(객체)를 제거


Object replace(Object k, Object v) : 기존의 키(k)의 값을 지정된 값(v)로 변경


Object put (Object key, Object value) :지정된 키와 값을 TreeMap에 저장


void putAll(Map map) : Map에 저장된 요소를 TreeMap에 저장


Object remove(Object key) : TreeMap에서 지정된 키로 저장된 값(객체)를 제거


Object replace(Object k, Object v) : 기존의 키(k)의 값을 지정된 값(v)으로 변경


boolean replace(Object key, Object oldValue, Object newValue) : 기존의 키(k)의 값을 새로운 값(newValue)로 변경, 기존의 값과 지정된 값(oldValue)가 일치해야 함


int size() : TreeMap에 저장된 요소의 개수를 반환


NaviableMap subMap(Object fromKey, boolean fromInclusive, Object toKey, boolean toInclusive) : 지정된 두개의 키 사이에 있는 모든 요소들이 담긴 NaviableMap을 반환. inclusive가 true이면 범위에 포함


SotretdMap subMap(Object fromKey, Object toKey) : 지정된 두 개의 키 사이에 있는 모든 요소들이 담긴 SortedMap을 반환(toKey는 포함되지 않음)


SortedMap tailMap(Object fromkey) : 지정된 키부터 마짐가 요소의 범위에 속한 요소가 담긴 SortedMap을 반환


NaviableMap tailMap(Object fromKey, boolean inclusive) : 지정된 키부터 마지막 요소의 범위에 속한 요소가 담긴 NaviableMap을 반환, inclusive가 true이면 fromKey도 포함


Collection values() : TreeMap에 저장된 모든 값을 컬렉션의 형태로 변환


import java.util.*;

public class TreeMapEx1 {

	public static void main(String[] args) {
		String[] data = { "A", "K", "A", "K", "D", "K", "A", "K", "K", "K",
				"Z", "D" };

		TreeMap map = new TreeMap();

		for (int i = 0; i < data.length; i++) {
			if (map.containsKey(data[i])) {
				Integer value = (Integer) map.get(data[i]);
				map.put(data[i], new Integer(value.intValue()) + 1);
			} else {
				map.put(data[i], new Integer(1));
			}
		}

		Iterator it = map.entrySet().iterator();

		System.out.println("기본정렬");
		while (it.hasNext()) {
			Map.Entry entry = (Map.Entry) it.next();
			int value = ((Integer) entry.getValue()).intValue();
			System.out.println(entry.getKey() + " : " + printBar('#', value)
					+ " " + value);
		}
		System.out.println();

		// map을 ArrayList로 변환한 다음에 Collections.sort로 정렬
		Set set = map.entrySet();
		List list = new ArrayList(set); // ArrayList(Collection c)

		// static void sort(List list, Comarator c)
		Collections.sort(list, new ValueComparator());

		it = list.iterator();

		System.out.println("값의 크기가 큰 순서대로 정렬");
		while (it.hasNext()) {
			Map.Entry entry = (Map.Entry) it.next();
			int value = ((Integer) entry.getValue()).intValue();
			System.out.println(entry.getKey() + " : " + printBar('#', value)
					+ " " + value);
		}

	}

	static class ValueComparator implements Comparator {
		public int compare(Object o1, Object o2) {
			if (o1 instanceof Map.Entry && o2 instanceof Map.Entry) {
				Map.Entry e1 = (Map.Entry) o1;
				Map.Entry e2 = (Map.Entry) o2;

				int v1 = ((Integer) e1.getValue()).intValue();
				int v2 = ((Integer) e2.getValue()).intValue();

				return v2 - v1;
			}
			return -1;
		}
	}

	public static String printBar(char ch, int value) {
		char[] bar = new char[value];

		for (int i = 0; i < bar.length; i++)
			bar[i] = ch;

		return new String(bar); // String(char[] chArr)
	}

}
==========================
기본정렬
A : ### 3
D : ## 2
K : ###### 6
Z : # 1

값의 크기가 큰 순서대로 정렬
K : ###### 6
A : ### 3
D : ## 2
Z : # 1

Properties

Properties는 HashMap의 구버전인 Hashtable을 상속받아 구현한 것으로, Hashtable은 키와 값을 (Object, Object)의 형태로 저장하는데 비해 Properties는 (String, String)의 형태로 저장하는 보다 단순화된 컬렉션 클래스이다.


Properties의 생성자와 메서드


Proeperties() : Properties객체를 생성한다.


Properties(Propertis defaults) : 지정된 Properties에 저장된 목록을 가진 Properties 객체를 생성한다.


String getProperty(String key) : 지정된 키(key)와 값(value)를 반환한다.


String getProperty(String key, String defaultValue) : 지정된 키(key)의 값(value)를 반환한다. 키를 못찾으면 defaultValue를 반환한다.


void list(PrintStream out) : 지정된 PrintStream에 저장된 목록을 출력한다.


void list(PrintWriter out) : 지정된 PrintWriter에 저장된 목록을 출력한다.


void load(InputStream inStream) : 지정된 InputStream으로부터 목록을 읽어서 저장한다.


void loatFromXML(InputStream in) : 지정된 InputStream으로부터 XML문서를 읽어서, XML문서에 저장된 목록을 읽어다 담는다. (load & store)


Enumeration propertyNames() : 목록의 모든 키(key)가 담긴 Enumberation을 반환한다.


void save(OutputStream out, String header) : deprecated되었으므로 store()를 사용


Object setProperty(String key, String value) : 지정된 키와 값을 저장한다. 이미 존재하는 키(key)면 새로운 값(value)로 바뀐다.


void store(Writer writer, String comments) : 저장된 목록을 지정된 Writer에 출력(저장)한다. comments는 목록에 대한 설명(주석)으로 저장된다.


void store(OutputStream out, String comments) : 저장된 목록을 지정된 OutputStream에 출력(저장)한다. comments는 목록에 대한 설명(주석)으로 저장된다.


void storeToXML(OutputStream os, String comment, String encoding) : 저장된 목록을 지정된 출력스트림에 해당 인코딩의 XML문서로 출력(저장)한다. comment는 목록에 대한 설명(주석)으로 저장된다.


Set StringPropertyNames() : Propertyies에 저장되어 있는 모든 키(key)를 Set에 담아서 반환한다.



import java.util.*;

public class PropertiesEx1 {

	public static void main(String[] args) {
		Properties prop = new Properties();

		// prop에 키와 값(key, value)을 저장한다.
		prop.setProperty("timeout", "30");
		prop.setProperty("language", "kr");
		prop.setProperty("size", "10");
		prop.setProperty("capacity", "10");

		// prop에 저장된 요소들을 Enumeration을 이용해서 ㅊ ㅜㄹ력한다.
		Enumeration e = prop.propertyNames();

		while (e.hasMoreElements()) {
			String element = (String) e.nextElement();
			System.out.println(element + "=" + prop.getProperty(element));
		}

		System.out.println();
		prop.setProperty("size", "20");// size의 값을 20으로 변경한다.
		System.out.println("size=" + prop.getProperty("size"));
		System.out.println("capacity=" + prop.getProperty("capacity", "20"));
		System.out.println("loadfactor="
				+ prop.getProperty("loadfactor", "0.75"));

		System.out.println(prop); // prop에 저장된 요소들을 출력한다.
		prop.list(System.out); // prop에 저장된 요소들을 화면(System.out)에 출력한다
	}

}
==========================
capacity=10
size=10
timeout=30
language=kr

size=20
capacity=10
loadfactor=0.75 <- loadfactor라는 키가 없기때문에 디폴트 값으로 지정한 0.75가 출력
{capacity=10, size=20, timeout=30, language=kr}
-- listing properties --
capacity=10
size=20
timeout=30
language=kr

Properties의 기본적인 메서드를 이용해서 저장하고 읽어오고 출력하는 방법을 보여주는 간단한예제이다. 데이터를 저장하는데 사용되는 setProperty()는 단순히 Hashtable의 put메서드를 호출할 뿐이다. 그리고 setProperty()는 기존에 같은 키로 저장된 값이 있는 경우 그 값을 Object타입으로 반환하며, 그렇지 않을 때는 null로 반환한다.

Object setProperty(String key, String value)

getProperty()는 Properties에 저장된 값을 읽어오는 일을 하는데, 만일 읽어오려는 키가 존재하지 않으면 지정된 기본값(defaultValue)을 반 환한다.

String getProperty(String key)
String getProperty(String key, String defaultValue)

Properties는 Hashtable을 상속받아 구현한 것이라 Map의 특성상 저장순서를 유지하지 않기 때문에 예제의 결과에 출력된 순서가 저장순서와는 무관하다는 것을 확인하자.

Properties는 컬렉션 프레임웍의 이전의 구버전이므로 Iterator가 아닌 Enumeration을 사용한다. 그리고 list메서드를 이용하면 Properties에 저장된 모든 데이터를 화면 또는 파일에 편리하게 출력할 수 있다.

void list(PrintStream out)
void list(PrintWriter out)

System.out은 화면과 연결된 표준출력으로 System클래스에 정의된 PrintStream타입의 static변수이다.

import java.io.*;
import java.util.*;

public class PropertiesEx2 {

	public static void main(String[] args) {
		//commandline에서 inputfile을 지정주지 않으면 프로그램을 종료한다.
		if(args.length != 1){
			System.out.println("USAGE: java PropertiesEx2 INPUTFILENAME");
			System.exit(0);
		}
		
		Properties prop = new Properties();
		
		String inputFile = args[0];
		
		try{
			prop.load(new FileInputStream(inputFile));
		}catch(IOException e){
			System.out.println("지정된 파일을 찾을 수 없습니다.");
			System.exit(0);
		}
		
		String name = prop.getProperty("name");
		String[] data= prop.getProperty("data").split(",");
		int max= 0, min =0;
		int sum =0;
		
		for(int i=0; i<data.length; i++){
			int intValue = Integer.parseInt(data[i]);
			
			if(i==0) max =min=intValue;
			
			if(max <intValue)
				max = intValue;
			else if(min>intValue)
				min = intValue;
			
			sum += intValue;
		}
		
		System.out.println("이름 : "+name);
		System.out.println("최대값 : "+max);
		System.out.println("최소값 : "+min);
		System.out.println("합계 : "+sum);
		System.out.println("평균 : "+(sum*100.0/data.length)/100);
	}

}

외부 파일(input.txt)로 부터 데이터를 입력받아서 계산결과를 보여주는 예제이다. 외부파일의 형식은 라인단위로 키와 값이 '='로 연결된 형태이어야 하며 주석라인은 첫번째 문자가 '#'이어야 한다.

 

정해진 규칙대로만 파일을 작성하면 load()를 호출하는 것만으로 쉽게 데이터를 읽어 올수 있다. 다만 인코딩(encoding)문제로 한글이 깨질 수 있기 때문에 한글을 입력받으려면 아래와 같이 코드를 변경해야 한다.

String name = prop.getProperty("name");

try{
	name = new String(name.getBytes("8859_1"), "EUC-KR");
}catch(Exception e) {}

파일로부터 읽어온 데이터를 변환해주는 과정이다.

우리가 사용하고 있는 OS의 기본 인코딩이 유니코드가 아니라서 변환이 필요하다.

  • key에 문자 '='를 포함시키고자 한다면 escape문자 \를 사용해서 \= 와 같이 표현한다.
import java.util.*;
import java.io.*;

public class PropertiesEx3 {

	public static void main(String[] args) {
		Properties prop = new Properties();
		
		prop.setProperty("timeout", "30");
		prop.setProperty("language", "kr");
		prop.setProperty("size", "10");
		prop.setProperty("capacity", "10");
		
		try{
			prop.store(new FileOutputStream("output.txt"), "Properties Example");
			prop.storeToXML(new FileOutputStream("output.xml"), "Properties Example");
		}catch(IOException e){
			e.printStackTrace();
		}
		

	}

}
============================
output.txt의 내용
#Properties Example
#Sat Jul 10 16:03:10 KST 2021
capacity=10
size=10
timeout=30
language=\uD55C\uAE00 <- 한글이 unicode로 바뀌어 있다.
==============================
output.xml의 내용
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>Properties Example</comment>
<entry key="capacity">10</entry>
<entry key="size">10</entry>
<entry key="timeout">30</entry>
<entry key="language">한글</entry> <- 한글이 그대로 저장되어 있다.
</properties>

이전 예제와는 반대로 Properties에 저장된 데이터를 store()와 stroeToXML()를 이용해서 파일로 저장하는 방법을 보여준다. 여기서도 한글문제가 발생하는데 storeToXML()로 저장한 XML은 Editplus나 Eclipse에서 한글편집이 가능하므로 데이터에 한글이 포함된 경우 store()보다는 stroeToXML()을 이용해서 XML로 저장하는 것이 좋다.

import java.util.*;
public class PropertiesEx4 {

	public static void main(String[] args) {
		Properties sysProperties = System.getProperties();
		System.out.println("java.version : "+sysProperties.getProperty("java.version"));
		
		System.out.println("user.language : "+sysProperties.getProperty("user.language"));
		
		sysProperties.list(System.out);
	}

}
=======================
java.version : 1.8.0_291
user.language : ko
-- listing properties --
java.runtime.name=Java(TM) SE Runtime Environment
sun.boot.library.path=C:\Program Files\Java\jdk1.8.0_291\jr...
java.vm.version=25.291-b10
java.vm.vendor=Oracle Corporation
java.vendor.url=http://java.oracle.com/
path.separator=;
java.vm.name=Java HotSpot(TM) 64-Bit Server VM
file.encoding.pkg=sun.io
user.script=
user.country=KR
sun.java.launcher=SUN_STANDARD
sun.os.patch.level=
java.vm.specification.name=Java Virtual Machine Specification
user.dir=D:\workspace\11CollectionsFramework
java.runtime.version=1.8.0_291-b10
java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment
java.endorsed.dirs=C:\Program Files\Java\jdk1.8.0_291\jr...
os.arch=amd64
java.io.tmpdir=C:\Users\sec\AppData\Local\Temp\
line.separator=

java.vm.specification.vendor=Oracle Corporation
user.variant=
os.name=Windows 10
sun.jnu.encoding=MS949
java.library.path=C:\Program Files\Java\jdk1.8.0_291\bi...
java.specification.name=Java Platform API Specification
java.class.version=52.0
sun.management.compiler=HotSpot 64-Bit Tiered Compilers
os.version=10.0
user.home=C:\Users\sec
user.timezone=
java.awt.printerjob=sun.awt.windows.WPrinterJob
file.encoding=UTF-8
java.specification.version=1.8
user.name=sec
java.class.path=D:\workspace\11CollectionsFramework\bin
java.vm.specification.version=1.8
sun.arch.data.model=64
java.home=C:\Program Files\Java\jdk1.8.0_291\jre
sun.java.command=PropertiesEx4
java.specification.vendor=Oracle Corporation
user.language=ko
awt.toolkit=sun.awt.windows.WToolkit
java.vm.info=mixed mode
java.version=1.8.0_291
java.ext.dirs=C:\Program Files\Java\jdk1.8.0_291\jr...
sun.boot.class.path=C:\Program Files\Java\jdk1.8.0_291\jr...
java.vendor=Oracle Corporation
file.separator=\
java.vendor.url.bug=http://bugreport.sun.com/bugreport/
sun.cpu.endian=little
sun.io.unicode.encoding=UnicodeLittle
sun.desktop=windows
sun.cpu.isalist=amd64

시스템 속성을 가져오는 방법을 보여주는 예제이다. System클래스의 getProperties()를 호출하면 시스템과 관련된 속성이 저장된 Properties를 가져올 수 있다. 이 중에서 원하는 속성을 getProperty()를 통해 얻을 수 있다.

'Back-end' 카테고리의 다른 글

11 컬렉션 프레임웍(7)  (0) 2021.07.11
SQL 문법(1)  (0) 2021.07.11
04 정확하고 다양한 결과 출력 WHERE절과 연산자  (0) 2021.07.10
11 컬렉션 프레임웍(5)  (0) 2021.07.09
11 컬렉션 프레임웍(4)  (0) 2021.07.08