컬렉션이란 배열처럼 동일한 타입을 묶어서 관리하는 자료구조입니다. 저장 공간의 크기 (capacity)를 동적으로 관리합니다.
프레임워크란 클래스를 정의하거나 설계할 때 어떤 원칙이나 구조를 가지고 클래스와 인터페이스를 설계한 것을 프레임워크라고합니다. ( 클래스와 인터페이스의 모임)
컬렉션 프레임워크란❓
컬렉션 프레임워크(Collection Framework)는 리스트, 스택, 큐, 트리 등의 자료구조에 정렬 , 탐색 등의 알고리즘을 구조화 해놓은 프레임워크이자 java에서 데이터 그룹을 다루기 위한 클래스들의 집합입니다.
프레임워크는 데이터 그룹을 저장하고 조작하기 위한 표준화된 방법을 제공하여 개발자들이 데이터 구조를 효율적으로 관리할 수 있도록 돕습니다. 이러한 컬렉션 프레임워크는 자바의 인터페이스(interface)를 사용하여 구현됩니다.
컬렉션 프레임워크는 다양한 인터페이스와 클래스로 구성되어 있으며, 각각의 클래스는 특정한 데이터 구조와 동작 방식을 가지고 있습니다. 주요한 인터페이스와 클래스로는 다음과 같은 것들이 있습니다
컬렉션 프레임워크는 데이터 그룹을 다루기 위한 다양한 기능들을 제공합니다. 데이터의 추가, 삭제, 검색, 정렬 등을 쉽게 처리할 수 있으며, 각각의 클래스는 내부적으로 데이터 구조를 효율적으로 관리하도록 구현되어 있습니다. 이를 통해 개발자는 데이터 구조에 대한 세부적인 관리 없이 간편하게 데이터를 다룰 수 있습니다.
1. List<E>
순서가 있는 데이터 그룹을 저장하는 인터페이스입니다. 컬렉션은 제네릭타입으로 선언되고 동일한 타입을 저장할 때, 제네릭 타입으로 선언된 데이터들만 초기화가 가능합니다. 중복된 요소를 허용하며, 대표적인 클래스로는 ArrayList, LinkedList, Vector 등이 있습니다.
배열의 경우, 초기화되면 저장크기가 고정이 되어 이 후 각 인덱스에 저장된 값들을 제거하거나 추가하더라도 인덱스의 총 길이는 동적으로 바뀌지가 않습니다. LIST의 경우, 동적 컬렉션을 생성하여 데이터의 추가 삭제가 가능합니다. 그에 따른 저장공간의 길이도 자동으로 늘어나고 줄게 됩니다.
💡 List <E> 컬렉션의 객체 생성 방법
① List <E> interface의 구현 클래스 생성자로 동적 컬렉션 생성 (데이터의 추가 삭제 가능)
- 기본 생성자의 경우 원소 개를 저장할 수 있는 저장공간(capacity)를 확보합니다. 필요한 경우에 추가한다면 JVM이 동적으로 저장공간의 크기를 자동적으로 추가합니다. ex) List<Integer> aList1 = new ArrayList<Integer>(); → capacity(10)
- 생성자 매개변수로 저장공간의 크기를 직접 넘겨줄 수 있습니다. (단, LinkedList<E>는 제외, capacity 지정 불가능) ex) List<Integer> aList2 = new ArrayList<Integer>(20) → capacity(20)
② Arrays.asList( T(개수가 지정되지 않은 매개변수) ..) 메서드를 이용하여 정적 컬렉션 생성
- 데이터의 추가(add) 삭제(remove) 불가능하며, 데이터의 변경(set)은 가능합니다. → 고정된 데이터를 저장하고 활용하고자 할 때 사용
ex) List<제네릭타입지정> asList1 = Arrays.asList(제네릭타입데이터들);
List<Integer> aList1 = Arrays.asList(1,2,3,4);
내부적으로는 1,2,3,4가 담겨져 있는 Integer배열이 만들어졌고, 해당 배열을 List로 감싼 객체가 생성됩니다.
여기서 내부적으로는 데이터가 고정적인 배열이 생성된 것이라 add() , remove()는 사용이 불가하고,
데이터의 수는 변하지 않고 값만 변하게 하는 set() 메서드만 사용가능합니다.
→ 배열처럼 수집(collect)한 원소(Element)를 인덱스(index)로 관리 List<E>의 구현 클래스는 아래의 모든 메서드를 포함합니다.
- toArray()메서드 : toArray() 메서드는 ArrayList의 요소들을 배열로 변환하는 메서드입니다. 이 메서드를 호출하면 ArrayList의 요소들이 배열로 복사되어 반환됩니다. toArray() 메서드에는 두 가지 형태가 있습니다
- 매개변수가 없는 toArray():
- 이 형태의 toArray() 메서드는 Object 배열로 요소들을 복사하여 반환합니다.
- 반환된 배열의 타입은 Object 배열이므로, 원하는 타입으로 형변환을 해주어야 합니다.
- 매개변수가 있는 toArray(T[] a):
- 이 형태의 toArray() 메서드는 지정한 타입의 배열 **a**를 매개변수로 받아, 해당 배열로 요소들을 복사하여 반환합니다.
- 만약 매개변수로 전달된 배열의 크기가 ArrayList의 크기보다 작을 경우, 새로운 배열이 생성되어 요소들이 복사됩니다.
- 만약 매개변수로 전달된 배열의 크기가 ArrayList의 크기보다 크거나 같을 경우, ArrayList의 요소들이 매개변수로 전달된 배열에 복사되고, 남는 공간은 null로 채워집니다.
Object[] object = aList3.toArray(); System.out.println(Arrays.toString(object)); Integer[] integer1 = aList3.toArray(new Integer[0]); System.out.println(Arrays.toString(integer1)); //출력 : [1,2,3] -> list인 aList3의 size()보다 작성된 선언공간이 크면 자동적으로 list의 size 크기를 가지는 배열이 생성 Integer[] integer2 = aList3.toArray(new Integer[5]); System.out.println(Arrays.toString(integer2)); //출력 [1,2,3,null,null] -> list인 aList3의 size()가 작성된 선언공간 new Integer[5]보다 작은 경우 데이터가 채워진 이 후의 공간에는 null값이 담기게 된다.
- 매개변수가 없는 toArray():
✅ 대표적인 List<E> 컬렉션의 클래스
- ArrayList<E> : ArrayList<E>는 제네릭을 사용하여 요소를 저장하는 동적 배열 클래스입니다. <E>는 제네릭 타입 매개변수로, ArrayList가 저장할 요소의 타입을 지정하는데 사용됩니다.
ArrayList를 사용하려면 import java.util.ArrayList; 문을 통해 java.util 패키지에서 해당 클래스를 임포트한 후, 다음과 같이 ArrayList 객체를 생성하고 요소를 추가하고 접근할 수 있습니다
import java.util.ArrayList; public class Main { public static void main(String[] args) { ArrayList<String> list = new ArrayList<String>(); // 요소 추가 list.add("사과"); list.add("바나나"); list.add("딸기"); // 요소 접근 String fruit = list.get(1); System.out.println(fruit); // 출력: 바나나 // 요소 삭제 list.remove(0); System.out.println(list); // 출력: [바나나, 딸기] } } 위의 예제에서 <String>은 ArrayList가 문자열 요소를 저장한다는 것을 명시하고 있습니다. 따라서 ArrayList에는 문자열만 저장할 수 있습니다. 만약 다른 타입의 요소를 저장하려면 <E> 자리에 해당 타입을 지정하면 됩니다.
- Vector<E> : Vector<E>는 Java의 컬렉션 프레임워크에서 제공하는 클래스로, 동적으로 크기가 조정되는 배열 형태의 자료구조입니다. ArrayList와 아주 유사하게 동일한 타입의 객체수집 (collection)` , 메모리의 동적할당, 데이터의 추가, 변경, 삭제 등의 메서드를 사용할 수 있는 공통적 기능을 제공하지만, 큰 차이점으론 Vector는 스레드 동기화(synchronized)가 되어 있어 멀티스레드 환경에서 안전하게 사용할 수 있습니다.
- LinkedList<E> : LinkedList<E>는 연결 리스트(linked list) 데이터 구조를 기반으로한 리스트(List) 구현체입니다. 앞뒤 요소(Element)로 정보의 데이터 위치를 관리합니다. LinkedList는 요소들을 연결한 노드(Node)로 구성되며, 각 노드는 데이터 요소와 다음 노드를 가리키는 참조(주소)로 이루어져 있습니다.
각 데이터들의 왼쪽 오른쪽 데이터들의 위치를 알고 있습니다. 이러한 구조로 인해 요소들의 추가, 삭제, 삽입이 상대적으로 빠르게 이루어질 수 있지만, 검색(get)은 속도가 더 늦게 진행됩니다. (순서를 세어서 해당 토드를 찾아야 하기때문에) - ArrayList<E>와 유사하지만 1) 디폴트 저장공간(10)만 사용하며 2) 생성자로 저장공간의 크기 지정이 불가한 점, 3) 데이터의 내부 저장방식이 index가 아닌 앞 뒤 객체의 위치정보를 저장한다는 차이점이 있습니다.
ArrayList<E>와 LinkedList<E> 가장 큰 차이점은 내부적인 데이터 구조입니다.
- 내부 데이터 구조:
- ArrayList: 배열(Array)을 기반으로한 동적 배열 구조입니다. 요소들은 인덱스에 따라 순차적으로 저장됩니다. 인덱스로 직접적인 접근이 가능하며, 요소의 삽입과 삭제가 느리지만 요소의 조회가 빠릅니다.
- LinkedList: 연결 리스트(Linked List)를 기반으로한 노드(Node)들이 연결된 구조입니다. 각 요소는 이전 노드와 다음 노드의 참조(주소)로 연결되어 있습니다. 요소의 삽입과 삭제가 빠르지만 인덱스로 직접적인 접근이 불가능하며, 요소의 조회가 느립니다.
- 데이터 접근 시간:
- ArrayList: 인덱스로 요소에 직접 접근할 수 있으므로 요소의 조회가 빠릅니다. 삽입과 삭제가 배열의 크기 변동에 따라 발생하므로 비용이 크고, 요소를 중간에 삽입 또는 삭제하는 경우에는 뒤따라오는 요소들을 한 칸씩 이동해야 합니다.
- LinkedList: 요소를 순차적으로 따라가야 하므로 인덱스로 직접 접근하는 것보다 접근 시간이 더 오래 걸립니다. 하지만 요소의 삽입과 삭제는 노드의 연결 관계만 변경하면 되므로 비교적 빠릅니다.
- 메모리 사용:
- ArrayList: 내부적으로 배열을 사용하기 때문에 요소들을 연속적인 메모리 공간에 저장합니다. 따라서 공간 효율성이 높습니다.
- LinkedList: 노드들이 연결되어 있기 때문에 각 요소마다 추가적인 노드 객체와 참조(주소)를 저장해야 하므로 메모리 사용량이 더 큽니다.
두 클래스는 사용 목적과 상황에 따라 선택되어야 합니다. ArrayList는 요소의 조회가 많고, 중간에 삽입/삭제가 적은 경우에 유리하며, LinkedList는 삽입/삭제가 빈번하고 순차적인 접근이 주로 발생하는 경우에 유리합니다.
'[ BACKEND] > JAVA_컬렉션 프레임워크' 카테고리의 다른 글
[JAVA] 람다식 (0) | 2023.07.12 |
---|---|
[JAVA] 컬렉션 프레임워크 Map<E> , Stack<E> (0) | 2023.07.11 |
[JAVA] 컬렉션 프레임워크 Set<E> (0) | 2023.07.09 |
[JAVA] 제네릭 클래스 vs 제네릭 메서드의 차이 (0) | 2023.07.04 |
[JAVA] GENERIC (제네릭) 이란 ? (1) | 2023.07.03 |