HashMap, Hashtable
Hashtable보다는 새로운 버전인 HashMap을 사용할 것을 권함
HashMap은 Map을 구현
키(key)와 값(value)을 묶어서 하나의 데이터(entry)로 저장
해싱(hashing)을 사용해 많은 양의 데이터를 검색하는데 있어서 뛰어난 성능 보임
키와 값을 Object타입으로 저장해 어떠한 객체도 저장가능
키(key) - 컬렉션 내의 키(key)중에서 유일해야 함
값(value) - 키(key)와 달리 데이터의 중복 허용
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
import java.util.HashMap;
import java.util.Scanner;
public class HashMapEx1 {
public static void main(String[] args) {
// 변수구성
// HashMap생성
// HashMap에 요소추가
// 아이디,비번저장
// 아이디, 비번입력받아서 맞는지 체크
// 변수구성
HashMap map = new HashMap();
// 요소추가
map.put("myId", "1234");
map.put("asdf", "1111");
map.put("asdf", "1234");
// 입력
Scanner scanner = new Scanner(System.in);
// 아이디, 비번체크
while(true) {
System.out.println("아이디와 비번입력해주세요");
System.out.print("id : ");
String id = scanner.nextLine().trim();
System.out.print("password : ");
String pwd = scanner.nextLine().trim();
System.out.println();
if(!map.containsKey(id)) { // HashMap에 해당하는 id(key)가 있는지?
System.out.println("해당하는 id가 없습니다.");
continue;
} else {
if(!map.get(id).equals(pwd)) { // id(key)에 해당하는 비번(value)가 입력한 비번과 일치하는지?
System.out.println("비밀전호가 일치하지 않습니다.");
} else {
System.out.println("로그인되었습니다.");
break;
}
}
}
}
}
|
cs |
출력
아이디와 비번입력해주세요
id : asdf
password : 1111
비밀전호가 일치하지 않습니다.
아이디와 비번입력해주세요
id : asdf
password : 1234
로그인되었습니다.
18행에 의해 asdf의 value값이 1111 -> 1234로 변경되어 저장됨
키는 중복이 안되기 때문에 새로 추가되지 않고 기존의 값을 덮어씀
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class HashMapEx2 {
public static void main(String[] args) {
// 변수구성
// HashMap생성
// 요소추가
// Map -> Set으로 변환
// 출력
// HashMap의 key반환 ( Set )
// 출력
// HashMap의 value반환 ( Collection )
// 출력
// 변수구성
HashMap map = new HashMap();
// 요소추가
map.put("김자바", new Integer(90));
map.put("김자바", new Integer(100));
map.put("이자바", new Integer(100));
map.put("강자바", new Integer(80));
map.put("안자바", new Integer(90));
// Map -> Set
Set set = map.entrySet(); // Map.Entry타입의 객체로 저장한 Set으로 반환
Iterator it = set.iterator();
while(it.hasNext()) {
Map.Entry e = (Map.Entry)it.next();
System.out.println("이름 : " + e.getKey() + "점수 : " + e.getValue());
}
// HashMap의 key반환 ( Set )
set = map.keySet(); // key반환, 반환형이 Set
System.out.println(set);
// HashMap의 value반환 ( Collection )
Collection value = map.values(); // value반환, 반환형이 Collection
it = value.iterator();
int total = 0;
while(it.hasNext()) {
total += (int)it.next();
}
System.out.println("총점 : " + total);
}
}
|
cs |
출력
이름 : 안자바점수 : 90
이름 : 김자바점수 : 100
이름 : 강자바점수 : 80
이름 : 이자바점수 : 100
[안자바, 김자바, 강자바, 이자바]
총점 : 370
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
package hashmap;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class HashMapEx3 {
static HashMap phoneBook = new HashMap();
public static void main(String[] args) {
addPhoneNo("친구", "이자바", "010-111-1111");
addPhoneNo("친구", "김자바", "010-222-2222");
addPhoneNo("친구", "김자바", "010-333-3333");
addPhoneNo("회사", "김대리", "010-444-4444");
addPhoneNo("회사", "김대리", "010-555-5555");
addPhoneNo("회사", "박대리", "010-666-6666");
addPhoneNo("회사", "이과장", "010-777-7777");
addPhoneNo("세탁", "010-888-8888");
printList();
}
// 그룹에 전화번호를 추가하는 메소드
static void addPhoneNo(String groupName, String name, String tel) {
addGroup(groupName);
HashMap group = (HashMap)phoneBook.get(groupName);
group.put(tel, name);
}
// 그룹을 추가하는 메소드
static void addGroup(String groupName) {
if(!phoneBook.containsKey(groupName))
phoneBook.put(groupName, new HashMap());
}
static void addPhoneNo(String name, String tel) {
addPhoneNo("기타", name, tel);
}
// 전화번호부 전체를 출력하는 메소드
static void printList() {
Set set = phoneBook.entrySet();
Iterator it = set.iterator();
while(it.hasNext()) {
Map.Entry e = (Map.Entry)it.next();
Set subSet = ((HashMap)e.getValue()).entrySet();
Iterator subIt = subSet.iterator();
System.out.println(" * "+e.getKey()+"["+subSet.size()+"]");
while(subIt.hasNext()) {
Map.Entry subE = (Map.Entry)subIt.next();
String telNo = (String)subE.getKey();
String name = (String)subE.getValue();
System.out.println(name + " " + telNo);
}
System.out.println();
}
}
}
|
cs |
출력
* 기타[1]
세탁 010-888-8888
* 친구[3]
이자바 010-111-1111
김자바 010-222-2222
김자바 010-333-3333
* 회사[4]
이과장 010-777-7777
김대리 010-444-4444
김대리 010-555-5555
박대리 010-666-6666
이해가 안된다. 다시 보자
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
package hashmap;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class HashMapEx4 {
// 변수구성
// String배열, HashMap
// String배열의 요소를 HashMap에 저장
// 배열의 각 요소와 숫자 1을 함께 저장
// 이미 저장되어 있으면 값을 1 증가
// key와 value출력
// value출력 시 printBar()메소드 이용
// printBar(char ch, int value) - value만큼 ch를 출력
public static void main(String[] args) {
// 변수구성
String[] data = {"A","K","A","K","D","K","A","K","K","K","Z","D"};
HashMap map = new HashMap();
// 배열 -> HashMap
for(int i=0; i<data.length; i++) {
if(map.containsKey(data[i])) { // 해당 요소가 이미 map에 있으면
Integer value = (Integer)map.get(data[i]); // map에 저장된 해당 요소의 value값 반환
map.put(data[i], new Integer(value.intValue() + 1)); // 기존 value값에 +1
} else {
map.put(data[i], new Integer(1));
}
}
Iterator it = map.entrySet().iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
int value = ((Integer)entry.getValue()).intValue();
System.out.println(entry.getKey() + " : " + printBar('#', value)
+ " " + value);
}
}
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);
}
}
|
cs |
출력
A : ### 3
D : ## 2
Z : # 1
K : ###### 6
해싱과 해싱함수
해싱
- 해시함수를 이용해서 데이터를 해시테이블에 저장하고 검색하는 기법
- 구현클래스로는 HashSet, HashMap, Hashtable등
- 사용하는 자료구조는 배열과 링크드 리스트의 조합을 사용
해시함수
- 데이터가 저장되어 있는 곳을 알려주어 다량의 데이터 중에서도 원하는 데이터를 빠르게 찾을 수 있음
저장할 데이터의 키를 해시함수에 넣으면 배열의 한 요소를 얻게되고, 그 곳에 연결되어 있는 링크드 리스트에 저장
TreeMap
- 이진검색트리의 형태로 기와 값의 쌍으로 이루어진 데이터를 저장
- 검색과 정렬에 적합한 컬렉션 클래스
- 검색에 관한 대부분의 경우는 HashMap이 성능이 더 뛰어남
- 범위검색이나 정렬이 필요한 경우엔 TreeMap사용
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
//변수구성
// String배열, TreeMap
// String배열의 요소를 TreeMap에 저장
// 배열의 각 요소와 숫자 1을 함께 저장
// 이미 저장되어 있으면 값을 1 증가
// key와 value 기본출력
// value출력 시 printBar()메소드 이용
// printBar(char ch, int value) - value만큼 ch를 출력
// TreeMap을 ArrayList로 변환
// 내림차순으로 정렬 후 출력
// Comparator로 내림차순정렬 정의
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();
// 배열 -> HashMap
for(int i=0; i<data.length; i++) {
if(map.containsKey(data[i])) { // 해당 요소가 이미 map에 있으면
Integer value = (Integer)map.get(data[i]); // map에 저장된 해당 요소의 value값 반환
map.put(data[i], new Integer(value.intValue() + 1)); // 기존 value값에 +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로 변환
Set set = map.entrySet();
List list = new LinkedList(set);
// Collections.sort()메소드로 정렬
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);
}
}
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);
}
}
// 내림차순 정렬을 정의하기 위해 정의한 클래스, Comparator구현
class ValueComparator implements Comparator {
@Override
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();
int v2 = (Integer)e2.getValue();
return v2 - v1; // 내림차순
}
return -1;
}
}
|
cs |
출력
= 기본정렬 =
A : ### 3
D : ## 2
K : ###### 6
Z : # 1
= 내림차순 정렬 =
K : ###### 6
A : ### 3
D : ## 2
Z : # 1
Properties
- Hashtable을 상속받아 구현
- (String, String)형태로 저장
- 어플리케이션 환경설정과 관련된 속성(property)을 저장하는데 사용
- 데이터를 파일로부터 읽고 쓰는 편리한 기능 제공
- 간단한 입출력은 Properties활용하면 좋음
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
29
30
31
32
33
34
35
36
37
|
import java.util.Enumeration;
import java.util.Properties;
public class PropertiesEx1 {
public static void main(String[] args) {
// 변수구성
// Properties생성
// Properties에 요소추가
// 요소들을 Enumeration이용해 출력
// 변수구성
Properties prop = new Properties();
// 요소추가
prop.setProperty("timeout", "30");
prop.setProperty("language", "kr");
prop.setProperty("size", "10");
prop.setProperty("capacity", "10");
// Enumeration이용해 출력
Enumeration e = prop.propertyNames(); // 저장되어 있는 key를 Set에담아 반환
while(e.hasMoreElements()) {
String element = (String)e.nextElement();
System.out.println(element+"="+prop.getProperty(element)); // element의 value값 반환
}
System.out.println();
prop.setProperty("size", "20");
System.out.println("size="+prop.getProperty("size"));
System.out.println("capacity="+prop.getProperty("capacity","20")); // capacity를 못찾으면 20반환
System.out.println("loadfactor="+prop.getProperty("loadfactor","0.75"));
System.out.println(prop);
prop.list(System.out);
}
}
|
cs |
출력
capacity=10
size=10
timeout=30
language=kr
size=20
capacity=10
loadfactor=0.75
{capacity=10, size=20, timeout=30, language=kr}
-- listing properties --
capacity=10
size=20
timeout=30
language=kr
Properties는 Hashtable을 상속받았으므로 Map특성상 저장순서 유지하지 않음
컬렉션프레임워크 이전의 구버전이기 때문에 Iterator가 아닌 Enumeration을 사용
list()로 Properties에 저장된 모든 데이터를 화면 또는 파일에 편리하게 출력가능
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class PropertiesEx2 {
public static void main(String[] args) {
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"); // 매개변수의 value값 반환
String[] data = prop.getProperty("data").split(",");
int max = 0, min = 0, 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);
}
}
|
cs |
출력
이름 : Seong Namkung
최대값 : 35
최소값 : 1
합계 : 111
평균 : 11.1
외부파일의 형식은 라인단위로 키와 같이 '='로 연결된 형태이어야 함, 주석은 첫번째문자가 '#'
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
|
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
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();
}
}
}
|
cs |
output.txt
output.xml
두개의 파일이 생성됨
1
2
3
4
5
6
7
8
9
10
|
import java.util.Properties;
public class PropertiesEx4 {
public static void main(String[] args) {
Properties sysProp = System.getProperties(); // 시스템 관련된 속성을 반환
System.out.println("java.version : " + sysProp.getProperty("java.version"));
System.out.println("user.language : " + sysProp.getProperty("user.language"));
sysProp.list(System.out); // 저장된 목록 출력
}
}
|
cs |
시스템 속성이 출력됨
Collections
- Arrays와 같이 fill(), copy(), sort(), binarySearch()등의 메소드 제공
- Arrays와 달리 컬렉션과 관련된 메소드를 제공 ( Arrays는 배열에 관련된 메소드 제공 )
컬렉션의 동기화
- 동기화가 필요한 경우에 Collections클래스의 동기화 메소드 사용
1
2
3
4
5
6
|
static Collection synchronizedCollection(Collection c)
static List synchronizedList(List list)
static Set synchronizedSet(Set s)
static Map synchronizedMap(Map m)
static SortedSet synchronizedSortedSet(SortedSet s)
static SortedMap synchronizedSortedMap(SortedMap m)
|
cs |
변경불가 컬렉션 만들기
- 컬렉션을 변경할 수 없게, 읽기전용으로 만들기 위함
- 멀티 쓰레드 프로그래밍에서 여러 쓰레드가 하나의 컬렉션을 공유하다보면 데이터가 손상될 수 있는데, 이를 방지위함
1
2
3
4
5
6
|
static Collection unmodifiabledCollection(Collection c)
static List unmodifiableList(List list)
static Set unmodifiableSet(Set s)
static Map unmodifiableMap(Map m)
static SortedSet unmodifiableSortedSet(SortedSet s)
static SortedMap unmodifiableSortedMap(SortedMap m)
|
cs |
싱글톤 컬렉션 만들기
- 인스턴스를 new연산자가 아닌 메소드를 통해서만 생성할 수 있게 함으로써 생성할 수 있는 인스턴스의 개수 제한
1
2
3
|
static List singletonList(Object o)
static Set singleton(Object o)
static Map singletonMap(Object key, Object value)
|
cs |
한 종류의 객체만 저장하는 컬렉션 만들기
1
2
3
4
5
6
|
static Collection checkedCollection(Collection c, Class type)
static List checkedList(List list, Class type)
static Set checkedSet(Set s, Class type)
static Map checkedMap(Map m, Class keyType, Class valueType)
static SortedSet checkedSortedSet(SortedSet s, Class type)
static SortedMap checkedSortedMap(SortedMap m, Class keyType, Class valueType)
|
cs |
'아카이브 > 자바의 정석' 카테고리의 다른 글
12장 지네릭스,열거형,애노테이션 20201111 (0) | 2020.11.11 |
---|---|
12장 지네릭스,열거형,애노테이션 20201110 (0) | 2020.11.10 |
11장 컬렉션프레임워크 20201106 (0) | 2020.11.06 |
11장 컬렉션 프레임워크 20201102 (0) | 2020.11.02 |
11장 컬렉션프레임워크 20201029 (0) | 2020.10.29 |