본문 바로가기
Java/Java

[자바의 정석_기초편] Chapter11. 컬렉션 프레임워크(Collections framework)_3

by HJ0216 2023. 6. 11.

이 글은 남궁성의 정석코딩 [자바의정석-기초편] 수강하며 정리한 글입니다.

 

 

🟣 기본 환경: IDE: Eclipse, Language: Java

 

 

 

Set: 순서X, 중복X

TreeSet: 이진 검색 트리(Binary Search Tree*)를 활용하여 자료 정렬

* Binary Search Tree: 조상 노드의 왼쪽에는 조상 노드보다 작은 값, 오른쪽에는 큰 값을 저장하는 이진트리, 첫 번째로 저장하는 값이 최고 조상 노드(=루트)가 됨

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.util.*;
 
public class Ex11_15 {
    public static void main(String[] args) {
        // set: 중복 X, 순서 X
        // treeSet: 중복 X, 순서 O
        // Constructs a new, empty tree set, sorted according to the natural ordering of its elements.
        TreeSet<Integer> set = new TreeSet<>();
        int[] scope = {80952045105550307510060};
        
        for(int i=0; i<scope.length; i++) {
            set.add(Integer.valueOf(scope[i]));
        }
        
        System.out.println("TreeSet: "+set);
        System.out.println("50보다 작은 값: "+set.headSet(50));
        // headSet: Returns a view of the portion of this set whose elements are strictly less than toElement.
        System.out.println("50보다 큰 값: "+set.tailSet(Integer.valueOf(50)));
        // from 포함, to 미포함
        // 50 -> new Integer(50) 자동 형변환
        System.out.println("From 40 to 80: "+set.subSet(4080));
    }
}
 
 
 

 

Set.HashSet: 순서(인덱스)X, 중복X*

* 값이 추가될 때마다, hashcode()->equals() 비교하여 모두 true일 경우, 동일 객체로 판단

 

합집합, 교집합, 차집합

* 계산 시, 초기값을 변경하지 말고 새로운 객체 생성(향후 계산 시 문제 발생)

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
94
95
96
import java.util.HashSet;
import java.util.Iterator;
 
public class Ex11_12 {
 
    public static void main(String[] args) {
        HashSet<Integer> setA    = new HashSet<>();
        HashSet<Integer> setB     = new HashSet<>();
        HashSet<Integer> setHab = new HashSet<>();
        HashSet<Integer> setKyo = new HashSet<>();
        HashSet<Integer> setCha = new HashSet<>();
        
        setA.add(1);
        setA.add(2);
        setA.add(3);
        setA.add(4);
        setA.add(5);
        System.out.println("setA: "+setA);
        
        setB.add(4);
        setB.add(5);
        setB.add(6);
        setB.add(7);
        setB.add(8);
        System.out.println("SetB: "+setB);
        
        // 합집합
        Iterator<Integer> it = setA.iterator(); // iterator는 일회용이므로 사용시마다 생성
        while(it.hasNext()) { // 읽어올 다음 요소가 있는 동안
            setHab.add(it.next()); // 요소 하나 꺼내오기
        }
        it = setB.iterator(); // iterator는 일회용이므로 사용시마다 생성
        while(it.hasNext()) {
            setHab.add(it.next());
        }
        System.out.println("setHab: "+setHab);
 
        // setA와 setB를 직접 건드리는 것은 차후 계산에 영향을 미치게되므로 새로운 참조변수 생성하여 진행
//        setA.addAll(setB); // 합집합, setB 모든 요소 추가(중복 제외)
//        System.out.println("Hab: "+setA);
 
        
        // 교집합
        Iterator<Integer> it2 = setA.iterator(); // iterator는 사용시마다 생성
        it2 = setB.iterator();
        while(it2.hasNext()) { 
            Integer tmp = it2.next(); 
            if(setA.contains(tmp)) {setKyo.add(tmp);}
        }
        System.out.println("setKyo: "+setKyo);
 
//        setA.retainAll(setB); // 공통된 요소만 남기고 삭제
//        System.out.println("Kyo: "+setA);
 
                
        // 차집합
        Iterator<Integer> it3 = setA.iterator();
        it3 = setA.iterator();
        while(it3.hasNext()) {
            Integer tmp = it3.next();
            if(!setB.contains(tmp)) {setCha.add(tmp);}
            // 만일 setB가 tmp(setA의 각 요소)를 포함하고 있지 않다면 setCha에 추가
        }        
        
        System.out.println("setCha: "+setCha);
        
//        System.out.println(setA);
//        System.out.println(setB);
//        setA.removeAll(setB); // 차집합, 공통된 요소 모두 제거
//        System.out.println("Cha: "+setA);
    }
}
import java.util.*;
 
public class Ex11_15 {
    public static void main(String[] args) {
        // set: 중복 X, 순서 X
        // treeSet: 중복 X, 순서 O
        // Constructs a new, empty tree set, sorted according to the natural ordering of its elements.
        TreeSet<Integer> set = new TreeSet<>();
        int[] scope = {80952045105550307510060};
        
        for(int i=0; i<scope.length; i++) {
            set.add(Integer.valueOf(scope[i]));
        }
        
        System.out.println("TreeSet: "+set);
        System.out.println("50보다 작은 값: "+set.headSet(50));
        // headSet: Returns a view of the portion of this set whose elements are strictly less than toElement.
        System.out.println("50보다 큰 값: "+set.tailSet(Integer.valueOf(50)));
        // from 포함, to 미포함
        // 50 -> new Integer(50) 자동 형변환
        System.out.println("From 40 to 80: "+set.subSet(4080));
    }
}
 
 
 

 

treeSet: 이진탐색정렬 -> 정렬기준 필요, 중복X

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
import java.util.*;
 
public class Ex11_13 {
    public static void main(String[] args) {
        // TreeSet(): 범위 검색 유리, 자동 정렬, 중복X
        Set<Object> treeSet = new TreeSet<>(new TestComp());
        // 정렬기준으 2개일 때는, TreeSet(정렬기준)이 우선 적용됨
        Set<Object> treeSet2 = new TreeSet<>();
 
        // HashSet: 정렬X
        Set<Object> hashSet3 = new HashSet<>();
 
        treeSet2.add(1);
        treeSet2.add(2);
        treeSet2.add(3);
        treeSet2.add(3); // 중복으로 treeSet에 저장X
        
        // Test class에서는 comparable을 구현하고 있지 않으므로 set.add를 할 경우 오류 발생
        for(int i=0; treeSet.size()<6; i++) {
            int num = (int)(Math.random()*45)+1;
//            treeSet.add(num); // AutoBoxing
            treeSet.add(Integer.valueOf(num));
            treeSet.add(new Test());
            // ClassCastException(형변환 예외): class Test cannot be cast to class java.lang.Integer)
            // set.add()는 이진탐색트리를 통해서 비교하면서 add()를 수행하는데 비교 기준이 없음
            // 비교기준을 만들어 treeSet 정렬기준에 대입: new TreeSet<>(new TestComp())
            hashSet3.add(num);            
        }
        
        treeSet.add(new Test());
        treeSet.add(new Test());
        treeSet.add(new Test());
        
        System.out.println("TreeSet: "+treeSet);
        System.out.println("TreeSet2: "+treeSet2);
        System.out.println("HashSet: "+hashSet3);
    }
}
 
class Test implements Comparable<Object> {
// Test class와 달리 스스로 비교 기준을 마련할 경우, treeSet 사용가능(예: Integer)
// treeSet 객체 생성 시 따로 비교기준 입력 필요 X: new TreeSet<>()
    @Override
    public int compareTo(Object o) {
        return 1;
    }    
}
 
class Test2 {}
// 비교 기준을 따로 구현하지 않았는데 Test2를 객체로하여 treeSet을 이용할 경우, Exception 발생
 
class TestComp implements Comparator<Object> {
// new Test2() 객체를 treeSet으로 구현하기 위한 비교 기준 마련
    @Override
    public int compare(Object o1, Object o2) {
        return -1// return을 0으로 했을 경우, o1, o2가 같다고 취급됨
    }
}
 
 
 

 

subSet()

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
import java.util.*;
 
public class Ex11_14 {
    public static void main(String[] args) {
        TreeSet<String> set = new TreeSet<>();
        
        String from = "b";
        String to    = "d";
        String to2  = "e";
        
        set.add("abc");
        set.add("apple");
        set.add("bcd");
        set.add("banana");
        set.add("cde");
        set.add("Car"); // 대문자가 가장 먼저 정렬
        set.add("car");
        set.add("document");
        set.add("drop");
        set.add("department");
        set.add("element");
        set.add("eating");
        set.add("frequence");
        set.add("flower");
        set.add("generic");
        set.add("grow");
        
        System.out.println("set: "+set);
        System.out.println("range search: "+set.subSet(from, to));
        // 대문자 미포함, to 미포함
        System.out.println("range search2: "+set.subSet(from, to2));        
        System.out.println("range search2: "+set.subSet(from, to+"zzz"));
        // to+"zzz"="dzzz"        
    }
}
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.util.*;
 
public class Ex11_15 {
    public static void main(String[] args) {
        // set: 중복 X, 순서 X
        // treeSet: 중복 X, 순서 O (이진탐색트리)
        TreeSet<Integer> set = new TreeSet<>();
        int[] scope = {80952045105550307510060};
        
        for(int i=0; i<scope.length; i++) {
            set.add(Integer.valueOf(scope[i]));
            // Integer는 자체적으로 Comparable을 구현하고 있으므로 따로 비교기준을 입력하지 않아도 됨
        }
        
        System.out.println("TreeSet: "+set);
        System.out.println("50보다 작은 값: "+set.headSet(50));
        // headSet: Returns a view of the portion of this set whose elements are strictly less than toElement.
        System.out.println("50보다 큰 값: "+set.tailSet(Integer.valueOf(50)));
        // from 포함, to 미포함
        // 50 -> new Integer(50) 자동 형변환
        System.out.println("From 40 to 80: "+set.subSet(4080));
    }
}
 
 
 

 

HashMap(Key, Value): 순서X, Key 중복X

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
import java.util.*;
 
public class Ex11_16 {
    public static void main(String[] args) {
        // HashMap: 순서X, key 중복X
        HashMap<Object, Object> map = new HashMap<>();
        map.put("abc""1234"); // put: 추가
        map.put("bcd""2345");
        map.put("bcd""3456"); // 최종 "bcd", "3456" 저장
        
        System.out.println(map.size());
        
        Scanner s = new Scanner(System.in);
        
        for(int i=0; i<3; i++) {
            System.out.println("Enter the ID and PW.");
            System.out.print("ID: ");
            String id = s.nextLine().trim(); // enter 단위로 입력 받음
            
            System.out.print("PW: ");
            String pw = s.nextLine().trim();
            System.out.println();
            
            if(!map.containsKey(id)) {
                System.out.println("There is no Identification.");
                System.out.println();
                continue;
                // 반복문 + continue = 아래 반복문 내용을 더이상 수행하지 않고 반복문 첫 문장으로 올라감
            }
            
            if(!map.get(id).equals(pw)) { // get(Object o): value값 반환
                System.out.println("Incorrect Password.");
                System.out.println();
            } else {
                System.out.println("Logined");
                break// 반복문 중단
            }
        } s.close(); // Resource leak: 's' is never closed
    }
}
 
 
 

 

형변환

Collection type value 값 반환 -> (Set) 형변환 X

객체를 부모로 만들고 리모컨을 자손으로 설정 할 수 X (실행할 수 없는 method가 있을 수도 있기 때문)

Map과 Set

Set<Map.Entry<String, Integer>> set = map.entrySet() // Set<Map.Entry<K,V>> entrySet()

Iterator<Map.Entry<K, V>> it = set.iterator<Map.Entry<K, V>>();

set = map.keySet(); // Set<K> keySet()

Set의 Generics를 <Map.Entry<String, Integer>>로 선언 시, Set<K> keySet()를 사용하지 못하는 문제 발생 -> Generics 선언 X

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.*;
 
public class Ex11_17 {
    public static void main(String[] args) {
        HashMap<String, Integer> map = new HashMap<>();
        map.put("Apple", Integer.valueOf(95));
        map.put("Apple", Integer.valueOf(100));
        map.put("Banana", Integer.valueOf(40));
        map.put("Car", Integer.valueOf(75));
        map.put("Document", Integer.valueOf(60));
        
        Set set = map.entrySet();
        // Set<Map.Entry<K, V>> entrySet(); -> 차후 Set<K> keySet() 사용 X (형변환X)
        // entrySet(): key, value 참조
        // set.iterator: map에서 쓸 수 없으므로 set으로 형 변환
        Iterator it = set.iterator();
        
        //<Map.Entry<String, Integer>>
        while(it.hasNext()) { // 읽을 요소가 남아있는지 확인
            Map.Entry e = (Map.Entry) it.next(); // 읽은 요소 map type으로 반환
            // Map interface 안에 Entry interface: 
            System.out.println("Name: "+e.getKey()+", Score: "+e.getValue());
        }
 
        set = map.keySet(); // Set type key값 반환
        System.out.println("NameList: "+set);
        
        Collection<Integer> collection = map.values();
        if(collection instanceof Set) {System.out.println("ScoreList: "+collection);}
        // Collection type value 값 반환 -> (Set) 형변환X
        // 객체를 부모로 만들고 리모컨을 자손으로 설정 할 수 X (실행할 수 없는 method가 있을 수도 있기 때문)
        else {System.out.println("Something is Worng.");}
        
        Collection<Integer> values = map.values(); 
        it = values.iterator();
        
        int total = 0;
        
        while(it.hasNext()) {
            Integer i = (Integer) it.next();
            total += i.intValue(); // Integer -> int
            // int i = (int) it.next(); // AutoBoxing
            // total += i;
        }
        
        System.out.println("Total: "+total);
        System.out.println("Average: "+(float)total/set.size());
        System.out.println("Max: "+Collections.max(values));
        System.out.println("Min: "+Collections.min(values));
    }
}
 
 
 

 

조상 class의 가용 method가 적을 때는 자손 class를 활용하여 더 많은 method 사용

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
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
 
public class Ex11_18 {
    public static void main(String[] args) {
        String[] data = {"A""B""A""D""C""B""A""B""A""D""D""C""D"};
        
        HashMap map = new HashMap();
        
        for(int i=0; i<data.length; i++) {
            if(map.containsKey(data[i])) {
                // map이 data[0](A)값을 갖고 있다면,
                int value = (int) map.get(data[i]);
                // value에 map에서 data[0]인 value를 반환
                map.put(data[i], value+1);
                // map에 data[0](key) value(value)값에 1을 추가
            } else {map.put(data[i], 1);}
            // map이 data[0]이 없다면 map에 key-data[0] value-1추가
        }
        
        Iterator it = map.entrySet().iterator();
        // Iterator: collection에 저장된 Element들을 읽어오는 방법을 표준화
        // map.entrySet() : Set type
        
        while(it.hasNext()) { // iteration이 읽어올 다음 요소가 있을 경우, true를 반환
            Map.Entry entry = (Map.Entry) it.next(); // iteration의 다음 element를 읽어옴
            int value = (int) entry.getValue(); // map에는 가용 method가 적으므로 map.entry 이용
            System.out.println(entry.getKey()+": "
                            +printBar('*', value)+" "+value);
        }
    }
    
    public static String printBar(char ch, int value) {
        char[] bar = new char[value];
        // bar에 길이가 value(4)인 char type 배열 생성
        
        for(int i=0; i<bar.length; i++) {
            bar[i] = ch;
        } return new String(bar); // char[] -> String
    }
}
 
 
 

 

list의 다양한 method()

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
import java.util.*;
import static java.util.Collections.*;
 
public class Ex11_19 {
    public static void main(String[] args) {
        List list = new ArrayList();
        System.out.println("list "+list);
        
        addAll(list, 1,2,3,4,5);
        // 원칙:Collections.addAll -> static을 import할 경우, class이름 생략 가능
        System.out.println("addAll "+list);
        
        rotate(list, 1);
        // 맨뒤 -> 맨 앞으로 이동하면서 회전
        System.out.println("rotate "+list);
        
        swap(list, 0,2);
        System.out.println("swap "+list);
        
        shuffle(list);
        System.out.println("shuffle "+list);
        
        sort(list);
        System.out.println("sort "+list);
        
        sort(list, reverseOrder());
        // 역순 정렬(reverse(list); 와 동일
        System.out.println("reverseOrderSort "+list);
        
        int idx = binarySearch(list, 3);
        System.out.println("IDX of 3 is "+idx);
        
        System.out.println("Max: "+max(list));
        System.out.println("Min: "+min(list));
        System.out.println("Min: "+max(list,reverseOrder()));
        
        fill(list, 9);
        System.out.println("fill "+list);
        
        List newList = nCopies(list.size(),2);
        // list와 같은 크기의 list를 생성하고, 2로 채움, 결과는 변경 불가
        System.out.println("newList "+newList);
        
        System.out.println("disjoint: "+disjoint(list, newList));
        // 공통요소가 1개도 없으면 true
        
        copy(list, newList); // newList에 있는 것을 list에 복사
        System.out.println("newList "+newList);
        System.out.println("list "+list);
        
        replaceAll(list, 21);
        System.out.println("replaceAll "+list);
        
        Enumeration e = enumeration(list);
        // iterator와 동일
        ArrayList list2 = list(e);
        System.out.println("ArrayList "+list2);        
    }
}
 
 
 

 

 

 

소스 코드

🔗 HJ0216/java-practice

 

참고 자료

 

Java - 11.1 TreeSet

- 이진 검색 트리(binary search tree)라는 자료구조의 형태로 데이터를 저장하는 컬렉션 클래스이다. - 정...

blog.naver.com

 

자바 맵 – keySet() vs. entrySet() vs. values() 메서드

1. 개요 이 사용방법(예제)에서는 Java에서 Map 인터페이스 의 세 가지 메서드인 keySet() , entrySet() 및 values() 에 대해 설명합니다. 이러한 메서드는 각각 키 집합, 키-값 매핑 집합 및 값 모음을 검색

recordsoflife.tistory.com