본문 바로가기
Java/Java

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

by HJ0216 2023. 6. 3.

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

 

 

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

 

 

subList로 추출한 ArrayList: 읽기 전용, 수정 필요 시 새로운 객체 생성 필요

indexOf(): 지정된 객체의 위치(인덱스) 반환

* Array.indexOf(객체) 1->new Integer(1)로 자동 형변환

a.retainAll(b): a에서 b와 겹치지 않는 부분 모두 삭제

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
import java.util.ArrayList; // ctrl + shift +o
import java.util.Collection;
import java.util.Collections;
 
public class Ex11_1 {
    public static void main(String[] args) {
        ArrayList list1 = new ArrayList(10);
        // 길이(용량, capacity)가 10인 ArrayList 작성
        
        // ArrayList에는 객채만 저장 가능: AutoBoxing(기본->참조)형으로 자동 형변환
        list1.add(2);
        list1.add(new Integer(4));
        Integer itg = new Integer(5);
        list1.add(itg);
        list1.add(Integer.valueOf(0));
        list1.add(Integer.valueOf(1));
        list1.add(Integer.valueOf(3));
        
        Collection sub = list1.subList(1,4);
        // 타입을 모를 때에는 해당 메서드의 매개변수로 올 수 있는 타입 검색(F3)
        ArrayList list2 = new ArrayList(sub);
//        ArrayList list2 = new ArrayList(list1.subList(1, 4)); // 1, 2, 3 출력
        // subList로 추출한 ArrayList는 읽기전용이므로 수정이 필요할 경우, 새롭게 객체 생성 필요
        print(list1, list2);
        
//        Collection: Interface, Collections: Util Class
        Collections.sort(list1); // 오름차순 정렬
        Collections.reverse(list1); // 오름차순 정렬 후 reverse: 내림차순 정렬
        Collections.sort(list2);
        print(list1, list2);
        
        System.out.println("list1.containsAll(list2): "+list1.containsAll(list2));
        System.out.println();
        
        list2.add("B"); // 위치 지정없을 경우, 가장 뒤에 추가
        list2.add("C");
        list2.add(2"A");
        print(list1, list2);
 
//        Collections.sort(list2);
        // 문자 추가 후 sort 실행 시, 정렬할 수 없음
        
        list2.set(4"AA");
        print(list1, list2);
        
        list1.add(0"1");
        print(list1, list2);
        
        // indexOf()는 지정된 객체의 위치(인덱스)를 알려준다.
        System.out.println("index: "+list1.indexOf("1")); // String 1
        System.out.println("index: "+list1.indexOf(1)); // int 1
        // Array.indexOf(객체) 1->new Integer(1)로 자동 형변환
        System.out.println("index: "+list1.indexOf(9)); // 없을 경우 -1 반환
        
        list1.remove(0); // index 0 삭제
        list1.remove(new Integer(1)); // Integer 1 삭제
        print(list1, list2);
        // Integer 1을 삭제하는 것인지 Index 1인 객체를 삭제하는 것인지 조심        
        
        System.out.println("list1.retainAll(list2): "+list1.retainAll(list2));
        // list2와 겹치는 부분 제외하고는 모두 삭제
        print(list1, list2);
        
        // list2에서 list1에 포함된 객체 삭제(뒤에서부터 삭제해줘야 부담이 적음)
        for(int i=list2.size()-1; i>=0; i--) {
            if(list1.contains(list2.get(i))) {list2.remove(i);}
            // 1. get(i)로 list2에서 한개씩 추출
            // 2. contains()로 꺼낸 객체가 list1에 있는지 확인
            // 3. remove(i)로 해당 객체를 list2에서 삭제
        }
        print(list1, list2);
 
        // list2에서 list1에 포함된 객체 삭제(뒤에서부터 삭제해줘야 부담이 적음)
        for(int i=0; i<list2.size(); i++) {
            if(list1.contains(list2.get(i))) {list2.remove(i);}
            // 1. get(i)로 list2에서 한개씩 추출
            // 2. contains()로 꺼낸 객체가 list1에 있는지 확인
            // 3. remove(i)로 해당 객체를 list2에서 삭제
        }
        print(list1, list2);
        
    }
    
    static void print(ArrayList list1, ArrayList list2) {
        System.out.println("list1: "+list1);
        System.out.println("list2: "+list2);
        System.out.println();
    }
}
 
 
 

 

Stack-push, pop

\"EXPRESION\" \\->""의 앞에 쓰여서 문자로 인식하게 도와줌

System.exit(0): JVM 강제종료(0: 정상 종료)

cf. return: 메소드 강제종료, break: 반복문 강제종료

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
import java.util.EmptyStackException;
import java.util.Stack;
 
public class Ex11_3 {
    public static void main(String[] args) {
        if(args.length!=1) {
            System.out.println("Usage: java Ex11_3 \"EXPRESION\"");
            // \"EXPRESION\" \\->""의 앞에 쓰여서 문자로 인식하게 도와줌
            System.out.println("Example: java Ex11_3 \"((2+3)*4)+5\"");
            System.exit(0);
            // JVM 강제종료(0: 정상 종료), return-메소드 강제종료, break-반복문 강제종료
        }
        
        Stack st = new Stack();
        String expression = args[0];
        System.out.println("expression: "+expression);
        
        try {
            for (int i=0; i<expression.length(); i++) {
                char ch = expression.charAt(i);
                // charAt(): 특정 위치의 문자 반환
                if(ch=='(') {st.push(ch+"");} // stack-push: 저장, ch+"": 문자화
                else if (ch==')') {st.pop();} // stack-pop: 제거
            }
            if(st.isEmpty()) {System.out.println("괄호가 일치합니다.");}
            else {System.out.println("닫는 괄호가 부족합니다.");}
        } catch(EmptyStackException e) {System.out.println(
                "여는 괄호가 부족합니다.");}        
    }
}
 
 
 

 

Queue

if continue : 반복문 내용을 수행하지 않고, 다시 반복문 시작으로 이동

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
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
 
public class Ex11_4 {
    static Queue<String> q = new LinkedList<String>();
//    static Queue<String> q = new LinkedList<>();
//    객체가 들어오더라도 데이터 타입이 일정하다면 지정해줄 때 안정적인 프로그래밍 가능
    static final int MAX_SIZE = 5// Queue에 최대 5개만 저장
    
        public static void main(String[] args) {    
            System.out.println("Enter the 'help'");
            
            while(true) {
                System.out.println(">>");
                try {
                    Scanner s = new Scanner(System.in);
                    String input = s.nextLine().trim();
                    // Scanner.next(): Space bar 단위 입력
                    // Scanner.nextLine(): Enter 단위 입력
                
                    if("".equals(input)) continue;
                    // if continue : 반복문 내용을 수행하지 않고, 다시 반복문 시작으로 이동
                    
                    else if (input.equalsIgnoreCase("q")) {System.exit(0);}
                    
                    else if (input.equalsIgnoreCase("help")) {
                        System.out.println("help: 도움말 제공");
                        System.out.println("q or Q: 프로그램 종료");
                        System.out.println("history: 최근 입력한 명령어를 "+MAX_SIZE+"개 보여줍니다.");
 
                    } else if (input.equalsIgnoreCase("history")) {
                        LinkedList<String> list = (LinkedList<String>) q;
                        // Queue F3->ctrl + o = 사용할 수 있는 method 확인 가능
                        // Queue에 method가 별로 없어서 Linkedlist로 형변환해서 사용
                    
                        final int SIZE = list.size();                    
                        for(int i=0; i<SIZE; i++)
                        // list.size()가 반복될 때마다 list리모컨을 눌러서 객체 내 size를 호출이 되는데,
                        // 상수값으로 고정되어있으면 상수로 넣어두기
                        {System.out.println((i+1)+"."+list.get(i));}
                        // LinkedList.get(): Returns the element at the specified position in this list.
 
                    } else {
                        save(input);
                        System.out.println(input);
                    }
                    s.close(); // scanner leakage close
                }
                catch(Exception e) {System.out.println("입력 오류입니다.");}
            }
        }
    
    public static void save(String input) {
        if(!"".equals(input)) {q.offer(input);} // queue에 offer 저장(추가)
        // if(input != null && !input.equals(""))
        // input값이 null이 아니고, ""빈문자열이 아니라면(빈문자열 != null)
        // input = null -> NullpointException
        // equal(null): 자동 처리 가능
        if(q.size()>MAX_SIZE) {q.remove();} // queue에서 제거(=poll)
    }
}
 
 

 

Iterator

Collection FrameWork에 저장된 요소를 읽어오는 방법을 표준화한 interface

Collection interface를 상속받는 list, set에서 사용 가능(Map X)

- boolean hasNext(): 읽어올 요소가 남아 있는가

- Object next(): 다음 요소를 읽어 옴

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
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
 
public class Ex11_5 {
    public static void main(String[] args) {
        Collection<Integer> list = new ArrayList<>();
        // 다형성: list && set implements collection
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
    
        // 일회용 -> 재사용 시, 객체 생성 필요
        Iterator<Integer> it = list.iterator();
        
        while(it.hasNext()) { // 확인
            Object obj = it.next(); // 호출 
            System.out.println(obj);
        }
        
        System.out.println();
        it = list.iterator();
        while(it.hasNext()) {
            Object obj = it.next();
            System.out.println(obj);
        }
            
        System.out.println();
        for(int i=0; i<list.size(); i++) {
            Object obj = ((ArrayList<Integer>) list).get(i);
            // get()은 Collection에 없으므로 형변환 필요: ((ArrayList<Integer>) list)
            System.out.println(obj);
        }
    }
}
 
 
 

 

향상된 for문

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int[] arr8 = new int[5];
Arrays.setAll(arr8, i -> (int)(Math.random()*10)+1);
 
 
for(int i : arr8) {
    char[] graph = new char[i];
    Arrays.fill(graph, '*');
}
 
/*
int i에 int[] arr8 값을 차례대로 대입하여 반복문 실행
반복문을 도는 횟수는 arr8.length (생략)
 
결과값:
arr8: [5, 3, 10, 7, 3]
 
5: *****
3: ***
10: **********
7: *******
3: ***
*/
 
 
 
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
import java.util.Arrays;
import java.util.Comparator;
 
public class Ex11_7 {
    public static void main(String[] args) {
        String[] strArr = {"Java""hello""world""Crispy""roll"};
        
        Arrays.sort(strArr); // sort에 정렬기준을 따로 제시하지 않으면 comparable에 의한 정렬
        System.out.println("strArr: "+Arrays.toString(strArr)); // 대문자 먼저 정렬
        
        Arrays.sort(strArr, String.CASE_INSENSITIVE_ORDER); // 대소문자 구분X
        System.out.println("strArr: "+Arrays.toString(strArr));
        
        Arrays.sort(strArr, new Descending()); // 역순 정렬
        System.out.println("strArr: "+Arrays.toString(strArr));
 
    }
 
}
 
class Descending implements Comparator<Object> {
// Comparator<Itg>가 안되는 이유: 비교 type이 Object로 선언되었기 때문..?
    public int compare(Object o1, Object o2) {
        if(o1 instanceof Comparable && o2 instanceof Comparable) { // instanceof 형변환 가능여부 확인
            Comparable<Object> c1 = (Comparable<Object>) o1;
            // comparable class의 compareTo method를 이용할 것으므로 Comparable class type으로 형변환 가능한지 확인
            Comparable<Object> c2 = (Comparable<Object>) o2;
            return c1.compareTo(c2)*-1;
            // -1을 곱해서 기본 정렬방식을 역으로 변경
            // c2.compareTo(c1)*-1;과 동일
        } return -1;
    }
}
 
 
 

 

Object는 모든 class의 조상

-> class의 조상이라는 뜻은 객체를 생성할 수 있다는 뜻으로 기본형 type은 속하지 않음

만일 object type 자리에 primitive type이 있다면 autoBoxing을 complier가 실행한 것

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
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
 
public class Ex11_9 {
    public static void main(String[] args) {
        Object[] objArr = {"1", Integer.valueOf(1), 1"2""2""3""3""4""4""4"};
        Set<Object> set = new HashSet<>();
        // Generics 설정 시, 참조 변수 type 확인
        
        for(int i=0; i<objArr.length; i++) {
            System.out.println(objArr[i]+"="+set.add(objArr[i]));
            // boolean add(Object o): 추가 유무에 따른 T/F 반환
            set.add(objArr[i]);
            // Set: 순서X, 중복X
        } System.out.println(set);
        // String "1" 과 Integer 1 구분 O, 중복값 제거
        // Integer 1, int 1 구분 X
        // AutoBoxing: int 1 -> Integer 1
        // objArr에 들어갈 수 있는 Object type: Wrapper class
        
        // HashSet에 저장된 요소들을 출력
        Iterator<Object> it = set.iterator(); // element read
        while(it.hasNext()) { // 읽을 요소가 남아있는지 확인
            System.out.println(it.next()); // 요소 하나 꺼내오기
        }
    }
}
 
 
 

 

set -> list 변환

Set<Integer> set = new HashSet<>();

List<Integer> list = new LinkedList<>(set);

List에 set을 대입하여 새로운 객체 생성

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.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
 
public class Ex11_10 {
    public static void main(String[] args) {
        Set<Integer> set = new HashSet<>();
        
        // set의 크기가 6보다 작은동안 1~45사이의 난수 저장
        for(int i=0; set.size()<6; i++) {
            int num = (int)(Math.random()*45)+1;
            set.add(num); // AutoBoxing: num -> new Integer(num)로 변환
        }
        
        System.out.println(set);
        // set: 기본 정렬 안되어있음
        List<Integer> list = new LinkedList<>(set); // 리스트 종류 무관
        Collections.sort(list);
        // sort의 매개변수로 올 수 있는 것이 List interface 뿐이므로, set -> list
        System.out.println(list);
    }
}
 
 
 

 

 

 

소스 코드

🔗 HJ0216/java-practice

 

참고 자료

 

자바(Java) 반복문 - Iterator(이터레이터)

이전 포스팅에서 컬렉션 프레임워크에 대해 포스팅을 했었던 적이 있습니다. https://blog.naver.com/cjy21...

blog.naver.com

 

JAVA #11. 향상된 for문. 배열복사. 임의의 정수 가져오기(Math.random)

JAVA #11. 향상된 for문, 배열복사, 임의의 정수 가져오기 향상된 For문 기존까지는 for문에 반복되는...

blog.naver.com