Collections Framework

컬렉션 프레임워크(Collection Framework)

Java Collections Framework는 Java에서 데이터를 저장, 처리 및 조작하는 데 사용되는 API(응용 프로그램 프로그래밍 인터페이스)의 집합입니다. 이 API를 사용하면 다양한 데이터 구조, 예를 들어 리스트, 집합, 맵 등을 생성하고 조작할 수 있습니다.

Java Collections Framework에는 여러 클래스와 인터페이스가 포함되어 있습니다. 예를 들어, List, Set 및 Map과 같은 인터페이스는 데이터를 저장하는 데 사용됩니다. 이러한 인터페이스의 구현체는 ArrayList, HashSet 및 HashMap과 같은 클래스입니다. 이러한 클래스는 데이터를 저장하고 처리하는 다양한 방법을 제공합니다.


핵심 인터페이스

Collection 상속도

자바에서 제공하는 컬렉션 프레임워크에서는 그룹을 크게 3가지 타입이 존재한다고 인식하면 됩니다. 특히나, List와 Set을 구현한 클래스는 비슷한 부분이 많아 해당 부분을 다시 뽑아서 Collection 인터페이스에 다시 정의 할 수 있지만 Map의 경우에는 전혀 다르기 때문에 상속을 받지 못합니다. 

 

Vector, Stack, HashTable, Properties와 같은 클래스들 컬렉션 프레임워크가 생기기 이전 부터 있던 클래스들로 현재는 잘 사용하지 않는 것을 추천한다고 합니다. 대체 사용 클래스로는 ArrayList와 HashMap이니 이 부분을 참고하시면 좋을 듯 합니다. 

 

Collection  타입 객체 생성 방법 

Collection은 인터페이스이기 때문에 우리가 알고 있듯이 자료구조를 생성할 수 있는 클래스들을 활용해서 Collection의 객체를 생성하면 됩니다. 해당 방식을 사용하는 이유는 한번 더 추상화를 하게 됨으로 여러가지 클래스들을 하나의 Collection인터페이스로 사용이 가능하다는 장점이 있기 때문에 해당 방식을 종종 사용한다고 합니다. 

Collection list = new ArrayList();
Collection set = new HashSet();

 

 

List 인터페이스

List인터페이스는 중복을 허용하고, 저장 순서를 유지되는 컬렉션을 구현하는데 사용됩니다.

List 상속도

 

Set 인터페이스

Set인터페이스는 중복을 허용하지 않고 저장순서가 유지되지 않느 컬렉션을 구현하는데 사용됩니다.

Set 상속도

 

Map인터페이스

Map인터페이스는 키(Key)와 값(Value)을 하나의 쌍으로 묶어서 저장하는 컬렉션 클래스를 구현하는데 사용됩니다. 키는 중복 될 수 없지만 값은 중복 될 수 있습니다. 

Map 상속도

Map.Entry 인터페이스
Map 자료구조를 출력하려고 하다보면 Map.Entry라는 것을 활용해서 Key, Value값을 출력하게 되는데, 그 때 사용되는 Map.Entry는 Map인터페이스의 내부 인터페이스이다. 

ArrayList

ArrayList는 Java Collections Framework의 하나로, 크기가 가변적인 배열을 구현하는 클래스입니다. ArrayList는 기본적으로 배열과 비슷한 방식으로 동작하지만, 크기가 가변적이기 때문에 동적으로 크기를 조정할 수 있습니다.

ArrayList의 내부 구현은 배열을 기반으로 하며, 요소를 추가하거나 삭제할 때 배열의 크기를 동적으로 조정하여 처리합니다. 따라서 ArrayList에서 요소를 추가하거나 삭제할 때는 일반적으로 배열의 크기를 조정하는 과정이 필요하기 때문에, 이 과정에서 성능상의 문제가 발생할 수 있습니다. 따라서 요소의 추가 및 삭제가 빈번하게 발생하는 경우에는 LinkedList와 같은 다른 자료구조를 고려해볼 수도 있습니다.

 

LinkedList

LinkedList는 Java Collections Framework의 하나로, 이전 노드와 다음 노드에 대한 참조를 사용하여 구현된 리스트입니다. 그리고 LinkedList는 ArrayList와 달리 요소의 추가 및 삭제가 빈번하게 발생할 때 성능이 우수합니다. 이는 LinkedList에서 요소를 추가하거나 삭제할 때 배열의 크기를 조정하지 않고, 단지 노드의 참조를 업데이트하면 되기 때문입니다. 따라서 대량의 데이터를 추가하거나 삭제하는 작업에 적합합니다.


LinkedList는 인덱스를 사용하여 요소에 접근할 수 없기 때문에, 요소에 접근하기 위해서는 순차적으로 접근해야 합니다. 또한 ArrayList와 달리 요소의 위치를 기반으로 한 정렬 및 검색 작업에서는 성능이 떨어질 수 있습니다. 따라서 LinkedList는 ArrayList와 달리 대량의 데이터를 조회하는 작업에는 적합하지 않을 수 있습니다.

 

알아두면 좋은 팁!
- 순차적으로 추가/삭제하는 경우에는 ArrayList가 LinkedList보다 빠르다.
- 중간 데이터를 추가/삭제하는 경우에는 LinkedList가 ArrayList보다 빠르다. 

Iterator

Iterator는 Java Collections Framework에서 제공하는 인터페이스 중 하나로, 컬렉션 요소를 순회하며 요소에 대한 접근 및 제어를 제공합니다. Iterator는 컬렉션 요소에 대한 순차 접근을 가능하게 하므로, 컬렉션에 저장된 모든 요소를 순회하고 처리할 수 있습니다.

Iterator 인터페이스는 다음과 같은 메서드를 제공합니다.

  • hasNext(): 다음 요소가 있으면 true를 반환하고, 그렇지 않으면 false를 반환합니다.
  • next(): 다음 요소를 반환합니다.
  • remove(): 컬렉션에서 마지막으로 반환된 요소를 삭제합니다.

 

Iterator를 사용하면 for-each 반복문과 같은 편리한 문법을 사용할 수 없지만, 컬렉션의 모든 요소에 접근할 수 있으며, 요소의 추가, 삭제 등의 작업도 가능합니다. 또한, Iterator는 컬렉션 요소의 구체적인 구현 방법과 상관없이 일관된 방법으로 요소에 접근할 수 있습니다.

 

사용예시

List list = new ArrayList(Arrays.asList(1,2,3,4,5));
Iterator iterator = list.iterator();

while (iterator.hasNext()){
    Integer next = (Integer) iterator.next();
    System.out.println(next);
}

 

ListIterator

ListIterator는 양방향으로 순회할 수 있고, Iterator와 달리 다음 요소와 이전 요소에 모두 접근할 수 있습니다. 또한, ListIterator는 Iterator보다 더 많은 요소 조작 기능을 제공하며, 요소의 추가, 수정, 삭제 등을 지원합니다.

 

사용예시

ArrayList<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("cherry");

ListIterator<String> iterator = list.listIterator();
while (iterator.hasNext()) {
    String element = iterator.next();
    System.out.println(element);
}

while (iterator.hasPrevious()) {
    String element = iterator.previous();
    System.out.println(element);
}

Arrays

Arrays 클래스는 다양한 배열 조작 메서드를 제공하여 배열의 조작과 관련된 코드를 간결하고 효율적으로 작성할 수 있도록 도와줍니다.

 

sort() 메서드

Arrays.sort() 메서드는 배열의 요소를 오름차순으로 정렬합니다. 이 메서드는 기본 타입 배열과 객체 타입 배열 모두에 대해 동작합니다.

int[] arr = {3, 1, 4, 2, 5};
Arrays.sort(arr);

 

binarySearch() 메서드

Arrays.binarySearch() 메서드는 배열에서 특정 요소를 이진 탐색으로 검색합니다. 이 메서드는 오름차순으로 정렬된 배열에서만 동작합니다.

int[] arr = {1, 2, 3, 4, 5};
int index = Arrays.binarySearch(arr, 4);

 

fill() 메서드

Arrays.fill() 메서드는 배열의 모든 요소를 특정 값으로 채웁니다.

int[] arr = new int[5];
Arrays.fill(arr, 0);

 

copyOf() 메서드

Arrays.copyOf() 메서드는 배열의 일부 또는 전체를 복사하여 새로운 배열을 생성합니다.

int[] arr = {1, 2, 3, 4, 5};
int[] newArr = Arrays.copyOf(arr, 3);

 

asList() 메서드

Arrays.asList() 메서드는 배열을 List로 변환해주는 메서드입니다. 이 메서드를 사용하면 배열을 List처럼 다룰 수 있습니다.

int[] arr = {1, 2, 3, 4, 5};
List<Integer> list = Arrays.asList(arr);

 

toString() 메서드

Arrays.toString() 메서드는 배열의 요소를 문자열로 변환하여 반환합니다. 이 메서드는 모든 기본 타입과 객체 타입의 배열에 대해 동작합니다.

int[] arr = {1, 2, 3, 4, 5};
String str = Arrays.toString(arr);

 

deepToString() 메서드

Arrays.deepToString() 메서드는 다차원 배열의 모든 요소를 문자열로 변환하여 반환합니다. 이 메서드는 모든 기본 타입과 객체 타입의 다차원 배열에 대해 동작합니다.

int[][] arr = {{1, 2}, {3, 4}, {5, 6}};
String str = Arrays.deepToString(arr);

Camparable

Comparable 인터페이스는 객체 자신의 정렬 방법을 지정할 수 있도록 해주는 인터페이스입니다. Comparable을 구현한 클래스는 정렬 가능한 클래스이며, Arrays.sort()나 Collections.sort()와 같은 정렬 메서드에서 사용됩니다.


Comparable 인터페이스에는 compareTo() 메서드가 정의되어 있습니다. 이 메서드는 자신과 비교 대상 객체를 비교하여 결과를 정수 값으로 반환합니다. 이때, 반환 값이 0보다 작으면 자신이 비교 대상 객체보다 작은 것으로 간주하고, 반환 값이 0이면 같은 것으로, 반환 값이 0보다 크면 비교 대상 객체보다 큰 것으로 간주합니다.

class Student implements Comparable<Student> {
    private int id;
    private String name;
    
    public int compareTo(Student other) {
        return this.id - other.id;
    }
}

Student[] students = new Student[3];
// 학생 정보를 입력한 후, 배열에 저장

Arrays.sort(students);

 

Comparator

Comparator 인터페이스는 객체를 정렬하는 방법을 지정할 수 있도록 해주는 인터페이스입니다. Comparable과 달리, 정렬하려는 객체의 클래스에 직접 구현할 필요 없이, 별도의 정렬 기준을 정의할 수 있습니다.


Comparator 인터페이스에는 compare() 메서드가 정의되어 있습니다. 이 메서드는 두 개의 비교 대상 객체를 인자로 받아 결과를 정수 값으로 반환합니다. 반환 값이 0보다 작으면 첫 번째 인자가 두 번째 인자보다 작은 것으로 간주하고, 반환 값이 0이면 같은 것으로, 반환 값이 0보다 크면 첫 번째 인자가 두 번째 인자보다 큰 것으로 간주합니다.

class StudentComparator implements Comparator<Student> {
    public int compare(Student a, Student b) {
        return a.getName().compareTo(b.getName());
    }
}

Student[] students = new Student[3];
// 학생 정보를 입력한 후, 배열에 저장

Arrays.sort(students, new StudentComparator());

HashSet

HashSet은 Java에서 제공하는 Set 인터페이스를 구현한 클래스 중 하나입니다. HashSet은 중복된 요소를 허용하지 않으며, 순서가 없는 요소들을 저장합니다.

 

입력 순서를 보장하는 Set을 만드려면... 
HashSet 클래스를 활용하는 것이 아닌 LinkedList 클래스로 Set을 구현을 하게 된다면 자료입력 순서도 보장 할 수 있습니다. 


HashSet은 내부적으로 HashMap을 사용하여 구현됩니다. 즉, HashSet에 저장된 요소들은 HashMap의 key로 저장되며, 모든 key의 value는 동일한 객체로 초기화됩니다.

HashSet의 주요 특징

중복된 요소를 허용하지 않음

HashSet은 중복된 요소를 저장하지 않습니다. 이미 HashSet에 존재하는 요소를 추가하려고 하면, 해당 요소는 무시됩니다.

순서가 없음

HashSet은 요소들을 저장할 때 순서를 고려하지 않습니다. 따라서, HashSet의 요소를 검색할 때는 순서에 의존할 수 없습니다.

빠른 검색 속도

HashSet은 내부적으로 HashMap을 사용하여 구현됩니다. HashMap은 해시 함수를 사용하여 key를 저장하므로, 검색 속도가 매우 빠릅니다.

 

 

'Language > Java' 카테고리의 다른 글

리플렉션(Reflection)  (0) 2023.05.11
제네릭스<Generics>  (0) 2023.05.03
객체 지향 프로그래밍(OOP)  (0) 2023.04.25
JVM GC(Garbage Collection)  (0) 2023.04.13
JVM(Java Virtual Machine)  (0) 2023.04.03