Home [Java 프로그래밍] 11강 - 컬렉션
Post
Cancel

[Java 프로그래밍] 11강 - 컬렉션

💡해당 게시글은 방송통신대학교 김희천 교수님의 'Java 프로그래밍' 강의를 개인 공부 목적으로 메모하였습니다.



학습 개요


  • 컬렉션이란 여러 원소를 저장하고 관리하는 자료구 조임
  • JCF는 컬렉션을 관리하기 위한 클래스와 인터페이스를 제공하는 통합 프레임워크임
  • Collection, Set, List, Queue, Map 등의 인터페이스와 그것을 구현한 HashSet, ArrayList, LinkedList, HashMap 등의 클래스 사용법을 학습함



학습 목표


  • JCF의 기본 구조를 설명할 수 있음
  • HashSet 클래스를 사용하여 프로그램을 작성할 수 있음
  • ArrayListLinkedList 클래스의 차이를 설명할 수 있음
  • HashMap 클래스를 사용하여 복잡한 자료를 관리할 수 있음



강의록


JCF

컬렉션이란

  • 여러 원소를 하나의 그룹으로 묶어 관리하기 위한 자료 구조
  • JCF는 컬렉션 즉, 데이터 목록을 관리하기 위한 인터페이스와 클래스의 모음
  • JCF(Java Collections Framework)
    • 컬렉션을 표현하고 다루기 위한 통합된 프레임 워크
      • 클래스와 인터페이스의 집합
      • 컬렉션을 다양한 방식으로 저장, 정렬, 검색, 수정하는 도구를 제공
    • 컬렉션을 일관 된 방법으로 다룰 수 있음
      • 표준화 된 인터페이스
        • 컬렉션을 다루기 위한 기능을 표현
      • 어떻게 표현되는 지와 상관없이 일관성 있게 다룸
      • 클래스
        • 인터페이스를 구현한 클래스를 제공

JCF의 구조

  • JCF의 인터페이스

    image.png

    • Set
      • 데이터의 순서는 의미가 없으며 중복을 허용하지 않는 자료 구조
    • List
      • 중복을 허용하고 순서가 있는 자료 구조
    • Queue
      • List와 유사하나 원소의 삽입/삭제가 FIFO 방식
    • Map
      • 원소가 <key, value>의 형태이며 키는 유일해야 함

JCF의 인터페이스와 클래스

  • java.util 패키지에 포함되며 제네릭 타입
  • 다루는 자료의 유형을 지정해야 함

    구분SetListQueueMap
    해시 테이블HashSet  HashMap
    배열 ArrayList, Vector, Stack  
    연결 리스트 LinkedListLinkedList 
    해싱 + 연결 리스트LinkedHashSet  LinkedHashMap
    정렬SortedSet  SortedMap
    트리TreeSet  TreeMap

컬렉션 객체의 선언

  • 변수 선언은 해당 인터페이스 유형으로, 객체 생성은 인터페이스를 구현하는 클래스를 사용

    1
    
      Set<Integer> set = new HashSet<>();
    
    1
    
      List<Integer> list = new ArrayList<>();
    
    1
    
      List<Integer> list = new LinkedList<>();
    
    1
    
      Queue<Integer> queue = new LinkedList<>();
    
    1
    
      Map<String, Integer> map = new HashMap<>();
    

Collection<E> 인터페이스

  • Set, List, Queue 에서 공통으로 지원해야 하는 기능을 정의
  • 원소의 삽입과 삭제 메소드

    메소드설명
    boolean add(E e)주어진 요소를 현재 컬렉션에 추가함, 성공적으로 추가되면 true를 리턴
    boolean addAll(Collection<? extends E> c)주어진 컬렉션의 모든 요소를 현재 컬렉션에 추가
    boolean remove(Object o)주어진 요소를 컬렉션에서 제거
    boolean removeAll(Collection<?> c)주어진 컬렉션에 포함된 모든 요소를 현재 컬렉션에서 제거
    boolean retainAll(Collection<?> c)현재 컬렉션의 요소 중 주어진 컬렉션에 있는 요소만 남김
    void clear()컬렉션의 모든 요소를 제거하여 비움
  • 원소 탐색 메소드

    메소드설명
    boolean contains(Object o)현재 컬렉션이 주어진 요소를 가지고 있으면 true를 리턴
    boolean containsAll(Collection<?> c)현재 컬렉션에 주어진 컬렉션의 모든 요소가 포함되어 있으면 true를 리턴
    boolean isEmpty()현재 컬렉션이 빈 컬렉션이면 true를 리턴
  • 기타 메소드

    메소드설명
    int size()현재 컬렉션에 포함된 요소의 개수를 리턴
    int hashCode()현재 컬렉션의 해시 코드값을 리턴
    Object[] toArray()현재 컬렉션을 객체의 배열로 변환하여 리턴
    Iterator<E> iterator()Iterator 객체를 리턴
    boolean equals(Object)두 컬렉션이 같은 요소를 같은 순서로 포함하면 true를 리턴

HashSet, ArrayList, LinkedList 클래스

HashSet 클래스 예제

  • HashSet 클래스 사용 예

    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.*;
        
      public class Main {
          public static void main(String args[]) {
              Set<String> set = new HashSet<String>(); // HashSet 객체를 생성
                
              // HashSet에 문자열 값 추가
              set.add("one"); 
              set.add("two");
              set.add("three"); 
              set.add("four");
                
              System.out.println(set.add(new String("one"))); // HashSet은 중복을 허용하지 않으므로 이미 존재하는 "one"을 추가하지 않음
              System.out.println(set.size()); // HashSet의 현재 크기를 출력
              System.out.println(set.contains("four")); // HashSet이 "four"라는 요소를 포함하고 있는지 확인
              System.out.println(set.contains("one")); // HashSet이 "one"이라는 요소를 포함하고 있는지 확인
              System.out.println(set.contains(new String("one"))); // "one"이라는 값이 존재하는지 확인
                
              set.remove("four"); // "four"라는 요소 제거
              set.remove(new String("one")); // "one"이라는 문자열 제거
              System.out.println(set.size());
                
              set.clear(); // HashSet의 모든 요소를 제거
              System.out.println(set.size()); // HashSet의 현재 크기를 출력 (모든 요소가 삭제되었으므로 크기는 0)
          }
      }
        
      // false
      // 4
      // true
      // true
      // true
      // 2
      // 0
    

ArrayList<E> 클래스

  • List 인터페이스를 구현한 클래스
    • 크기 조절이 가능한 배열로 구현
  • 같은 자료가 중복 될 수 있으며, 입력 된 순서대로 관리 됨
    • 특정 위치의 자료를 참조하기 위해 첨자를 사용할 수 있음
  • List 인터페이스를 살펴봐야 함
  • 주요 메소드
    • boolean add(E e)
      • 원소를 맨 뒤에 삽입
    • void add(index, E element)
      • 해당 위치에 원소를 삽입
    • boolean remove(Object o)
      • 삭제에 성공하면 true를 리턴
    • E remove(int index)
      • 삭제 되는 원소를 리턴
    • E get(int index)
      • 해당 위치의 원소를 리턴
    • E set(int index, E element)
      • 기존 원소를 리턴
    • int indexOf(Object o)
      • 리스트 내에서 지정된 객체가 처음으로 등장하는 인덱스 리턴
      1
      2
      3
      4
      5
      6
      7
      
        List<String> list = new ArrayList<>();
        list.add("apple");
        list.add("banana");
        list.add("apple");
              
        System.out.println(list.indexOf("apple"));  // 0
        System.out.println(list.indexOf("grape")); // -1
      
    • int lastIndexOf(Object o)
      • 리스트 내에서 지정된 객체가 마지막으로 나타난 위치의 인덱스 리턴
      1
      2
      3
      4
      5
      6
      7
      
        List<String> list = new ArrayList<>();
        list.add("apple");
        list.add("banana");
        list.add("apple");
              
        System.out.println(list.lastIndexOf("apple"));  // 2
        System.out.println(list.lastIndexOf("grape")); // -1
      
    • List<E> subList(int from, int to)
      • 지정된 범위(from부터 to 전까지)의 리스트(서브 리스트)를 반환
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      
        List<String> list = new ArrayList<>();
        list.add("apple");
        list.add("banana");
        list.add("cherry");
              
        List<String> subList = list.subList(0, 2); // "apple", "banana"
        System.out.println(subList); // [apple, banana]
              
        list.set(1, "blueberry"); // 원본 리스트 변경 시 서브리스트도 반영됨
        System.out.println(subList); // [apple, blueberry]
      
    • ListIterator<E> listIterator()
      • 리스트 내의 요소를 양방향(앞으로 또는 뒤로)으로 탐색할 수 있는 리스트 반복 자 반환
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      
        List<String> list = new ArrayList<>();
        list.add("apple");
        list.add("banana");
              
        // 리스트 반복자를 생성
        ListIterator<String> it = list.listIterator();
              
        // 다음 요소 탐색
        while (it.hasNext()) {
            System.out.println(it.next());
        }
        // apple, banana
      
    • ListIterator<E> listIterator(int index)
      • 특정 인덱스(index)에서 시작하는 리스트 반복 자를 반환
      • 인덱스가 유효하지 않을 경우 IndexOutOfBoundsException이 발생
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      
        List<String> list = new ArrayList<>();
        list.add("apple");
        list.add("banana");
        list.add("cherry");
              
        // 1번 인덱스부터 시작하는 Iterator 생성
        ListIterator<String> it = list.listIterator(1);
              
        while (it.hasNext()) {
            System.out.println(it.next());
        }
        // banana, cherry
      

ArrayList 클래스 예제

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.*;

public class Main {
    public static void main(String args[]) {
        List<String> list = new ArrayList<String>();
        
        list.add("one");
        list.add("two");
        list.add("three");
        list.add(1, "one");
        list.add("five");
        
        System.out.println(list.size());
        System.out.println(list.indexOf("one"));
        System.out.println(list.get(2));
        System.out.println(list.lastIndexOf("one"));
        System.out.println(list.set(3, "four"));
        System.out.println(list.remove(4));
        System.out.println(list.remove("one"));
    }
}

// 5
// 0
// two
// 1
// three
// five
// 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
import java.util.*;

public class Main {
    public static void main(String args[]) {
        List<String> list = new ArrayList<String>();
        
        list.add("one");
        list.add("two");
        list.add("three");
        list.add("four");
        list.add("five");
        
        // for 구문을 이용한 자료 탐색
        for (int i = 0; i < list.size(); i++)
            System.out.println(list.get(i));
        
        // 향상된 for 구문을 이용한 자료 탐색
        for (String s : list)
            System.out.println(s);
        
        // Iterator 인터페이스를 이용한 자료 탐색
        Iterator<String> it = list.iterator();
        while (it.hasNext())
            System.out.println(it.next());
    }
}

// one
// two
// three
// four
// five
// one
// two
// three
// four
// five
// one
// two
// three
// four
// five
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.util.*;
import java.util.function.Consumer;

public class Main {
    public static void main(String args[]) {
        List<String> list = new ArrayList<String>();
        
        list.add("one");
        list.add("three");
        list.add("two");
        list.add(1, "one");
        
        // Consumer 인터페이스를 활용해 accept 메서드를 직접 구현한 익명 클래스
        Consumer<String> con1 = new Consumer<>() {
		        // Consumer 인터페이스의 추상 메서드 accept를 구현
            public void accept(String t) {
                System.out.println(t);  // 각 요소를 처리
            }
        };
        
        // 리스트의 각 요소에 대해 con1의 accept 메서드를 실행 
        list.forEach(con1);
        
        // 람다식을 사용하여 Consumer의 동작 구현 
        Consumer<String> con2 = t -> System.out.println(t);
        // 리스트의 각 요소를 처리하며 출력
        list.forEach(con2);
        
        // 리스트의 각 항목에 대해 직접 람다 표현식 전달
        list.forEach(t -> System.out.println(t));
    }
}

// one
// one
// three
// two
// one
// one
// three
// two
// one
// one
// three
// two

Iterator<E> 인터페이스

  • 컬렉션에 저장 된 원소를 차례대로 다룰 수 있음
  • 다음 메소드를 제공
    • boolean hasNext()
      • 순회할 다음 요소가 있으면 true 리턴
    • E next()
      • 다음 요소를 리턴하고, 커서를 다음 위치로 이동
    • void remove()
      • next()로 반환된 가장 최근 요소를 컬렉션에서 삭제
  • 컬렉션 HashSet, ArrayList, LinkedList 등에서 Iterator 객체를 리턴하는 iterator() 메소드를 사용할 수 있음

    1
    2
    3
    4
    5
    6
    
      List<String> list = new ArrayList<String>();
        
      Iterator<String> it = list.iterator(); // Iterator 객체 얻기
        
      while (it.hasNext()) // 다음 요소가 있는지 확인
          System.out.println(it.next());  // 다음 요소 가져와 출력
    

LinkedList 클래스

  • ArrayList와 마찬가지로 List 인터페이스를 구현한 클래스
    • 앞의 예제에서 ArrayListLinkedList로 바꿔도 됨
  • 스택 자료 구조에서 필요한 메소드도 제공함
    • 앞에서 넣거나 삭제

      1
      
        void push(E)
      
      1
      
        E pop()
      
  • Queue 인터페이스도 구현함
    • 뒤에서 원소를 추가함

      1
      
        boolean add(E)
      
      1
      
        boolean offer(E)
      
    • 앞의 원소를 삭제하고 리턴함

      1
      
        E poll()
      
      1
      
        E remove()
      
    • 앞의 원소를 읽음

      1
      
        E peek()
      
      1
      
        E element()
      

LinkedList를 이용하여 큐를 구현한 예제

  • LinkedList 클래스로 큐 구현하기

    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 Main {
          public static void main(String args[]) {
              LinkedList<String> queue = new LinkedList<String>();
                
              queue.offer("one");
              queue.offer("two");
              queue.offer("three");
              queue.offer("four");
                
              String s = queue.poll();
                
              while (s != null) {
                  System.out.println(s);
                  s = queue.poll();
              }
          }
      }
        
      // one
      // two
      // three
      // four
    

HashMap 클래스

Map<K, V> 인터페이스

  • (key, value)로 이루어진 원소로 구성되는 컬렉션을 다루기 위한 인터페이스
    • key는 중복되지 않으며, 하나의 key에 하나의 value만 대응됨
    • 원소들의 순서는 중요하지 않음
  • 주요 메소드

    메소드설명
    V put(K key, V value)맵에 <키, 값> 매핑을 추가, 키가 존재하면 값이 변경됨
    V get(Object key)맵에서 키와 매핑 된 값을 리턴, 없으면 null을 리턴
    V remove(Object key)키에 대응하는 매핑을 제거하고 값을 리턴, 없으면 null
    boolean containsKey(Object key)지정된 키가 맵에 있으면 true를 리턴
    Collection<V> values()맵에 존재하는 값들로 구성된 컬렉션을 리턴
    Set<K> keySet()맵에 존재하는 키들로 구성된 Set 객체를 리턴

HashMap 클래스

  • 해싱을 이용하여 Map 인터페이스를 구현한 클래스
    • 자료 탐색 방법이 ArrayListLinkedList 클래스와 다름
  • 복잡한 자료 관리(교재의 예)

    image.png

복잡한 자료 관리 – HashMap 클래스 예제

  • 성적 관리 프로그램

    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
    
      Map<String, Integer> lectures; // 학생별 과목 점수를 저장할 Map 생성 선언
      Map<String, Map<String, Integer>> scores = new HashMap<>(); // String, Map<String,Integer>로 타입 명시
    
      List<String> names = new ArrayList<String>(); // 학생의 이름을 담을 리스트 생성
      names.add("김철수"); names.add("이영희");
    
      Iterator<String> it = names.iterator(); // 이름 리스트를 순회하기 위해 Iterator 생성
    
      // 이름 리스트의 각 학생에 대해 과목 점수를 설정
      while (it.hasNext()) {
          String name = it.next();  // 다음 이름 가져오기
            
          if (name.equals("김철수")) {
              lectures = new HashMap<String, Integer>(); // 새로운 과목 점수를 저장할 HashMap 생성
              lectures.put("국어", 100);
              lectures.put("영어", 95);
              lectures.put("수학", 80);
              scores.put(name, lectures);  // 전체 점수 Map(scores)에 추가
          } else {
              lectures = new HashMap<String, Integer>();
              lectures.put("국어", 90);
              lectures.put("영어", 95);
              lectures.put("수학", 95);
              scores.put(name, lectures);
          }
      }
    
      Iterator<String> it2 = names.iterator();
    
      while (it2.hasNext()) {
          String name = it2.next();
          System.out.println(name);
          System.out.print("국어 : ");
          System.out.println(scores.get(name).get("국어")); // scores.get(name)으로 Map<String, Integer> 얻고 다시 get("과목")
          System.out.print("영어 : ");
          System.out.println(scores.get(name).get("영어"));
          System.out.print("수학 : ");
          System.out.println(scores.get(name).get("수학"));
          System.out.println();
      }
    
      // 김철수
      // 국어 : 100
      // 영어 : 95
      // 수학 : 80
    
      // 이영희
      // 국어 : 90
      // 영어 : 95
      // 수학 : 95
    



학습 정리


  • 컬렉션은 여러 원소를 저장하고 관리하는 객체를 통칭하는 용어이며, JCF는 컬렉션을 효율적으로 다루기 위한 API를 제공하는 프레임워크임
  • Set은 원소의 순서에 의미가 없고 중복을 허용하지 않는 컬렉션을 다루기 위한 인터페이스임
  • ListQueue는 자료의 중복을 허용하고 순서에 의미가 있는 컬렉션을 관리하기 위한 인터페이스임
    • Queue는 FIFO 방식으로 자료를 관리하는 인터페이스임
  • Map 인터페이스는 <키, 값>의 쌍으로 구성되는 자료의 묶음을 관리하는 메소드를 제공함
  • LinkedList 클래스는 List 인터페이스와 Queue 인터페이스를 모두 구현한 클래스이며, 스택 자료구조에서 필요한 메소드도 제공함



연습 문제


  1. ArrayList 클래스에 관한 설명으로 적당하지 않은 것은?

    a. 같은 자료를 중복으로 저장할 수 없다.

    • ArrayList 클래스에 대한 설명으로 적당한 것
      • List 인터페이스를 구현한 클래스임
      • 여러 원소를 저장하기 위해 내부적으로 배열을 사용함
      • 원소의 순서가 의미를 가짐
      • 같은 자료를 중복으로 저장할 수 있음
  2. (key, value) 형태의 원소로 구성되는 자료 묶음을 다루기 위한 인터페이스나 클래스가 아닌 것은?

    a. HashSet

    • (key, value) 형태의 원소로 구성되는 자료 묶음을 다루기 위한 인터페이스나 클래스
      • HashMap
      • Hashtable
      • Map
  3. LinkedList<E>를 이용하여 큐 자료구조를 구현할 때, 자료를 추가하는 메소드와 삭제하는 메소드는 무엇인가?

    a. 추가 시 boolean offer(E), boolean add(E), 삭제 시 E remove()

[데이터베이스 시스템] 11강 - 인덱싱

[운영 체제] 11강 - 장치 관리