본문 바로가기
Java

JAVA List, ArrayList, LinkedList

by 차가운개발 2024. 10. 3.

List는 자바 컬렉션 프레임워크에서 제공하는 인터페이스로 순서가 있는 요소의 집합을 다루기 위한 자료 구조다.

List 인터페이스를 구현한 대표적인 클래스로는 ArrayList, LinkedList, Vector등이 있다.

 

ㅇ List의 특징

  • 순서 유지
    List는 요소가 추가된 순서를 유지한다. 따라서 요소를 삽입하면 삽입 된 순서대로 요소가 저장된다.
  • 중복 허용
    Set과 달리 List는 동일한 요소를 여러 번 저장할 수 있다. 같은 값의 요소가 리스트에 여러 번 존재할 수 있다.
  • 인덱스 기반 접근
    List의 요소는 배열처럼 인덱스를 사용하여 접근할 수 있다. 배열과 같이 0부터 시작한다.

 

ㅇ List와 Array(배열)의 차이점

  • 동적 크기
    배열은 크기가 고정되어 있지만, List는 크기를 동적으로 조절할 수 있다. 요소를 추가하거나 제거할 때 자동으로 크기가 변경된다.
  • 다양한 구현체
    List는 인터페이스이기 때문에 다양한 방식으로 구현될 수 있다. 배열 기반의 ArrayList와 연결 리스트 기반의 LinkedList는 각각의 특성에 따라 다른 성능을 제공하므로, 상황에 맞는 구현체를 선택할 수 있다.
  • 컬렉션 프레임워크와 호환성
    List는 자바 컬렉션 프레임워크의 일부로, 다른 컬렉션 클래스와 쉽게 상호작용이 가능하고, 다양한 유틸리티 메서드를 사용할 수 있다.

ㅇ 주요 메서드

  • add()
    리스트의 끝에 요소를 추가하거나, 특정 위치에 요소를 삽입할 수 있다.
  • remove()
    리스트에서 특정 요소를 제거하거나, 인덱스를 기반으로 요소를 삭제할 수 있다.
  • get()
    특정 인덱스에 있는 요소를 반환한다.
  • set()
    지정된 인덱스에 있는 요소를 다른 값으로 바꾼다.
  • size()
    리스트에 저장된 요소의 개수를 반환한다.
  • clear()
    리스트에 있는 모든 요소를 제거하여 빈 리스트를 만든다.
  • contains()
    리스트에 특정 요소가 포함되어 있는지 확인한다.
  • subList()
    리스트에서 지정된 범위의 리스트를 반환한다.

 

 

ㅇ ArrayList와 LinkedList

둘 다 자바의 List 인터페이스를 구현한 대표적인 클래스들이지만, 내부적으로 매우 다른 방식으로 동작하며 성능의 차이도 크다. 이를 이해하여 각각의 자료구조를 적절한 상황에서 사용하는 것은 매우 중요하다. 

 

데이터의 구조

  • ArrayList
    내부적으로 동적 배열을 사용한다. 크기가 고정된 배열처럼 보이지만, 데이터가 추가될 때 배열이 꽉 차면 자동으로 더 큰 배열을 할당하고 기존의 배열을 복사하여 옮기는 방식으로 동적 배열을 유지한다. 
    배열처럼 연속된 메모리 공간에 저장되므로 메모리 접근 속도가 빠르다.
    출처: https://www.codelatte.io/courses/java_programming_basic/5N27027VT1DBUAX0
  • LinkedList
    이중 연결 리스트를 사용한다. 각 노드는 데이터와 함께 다음 노드와 이전 노드를 가리키는 참조를 가지고 있다.
    연속되지 않은 메모리 공간에 저장된다. 각 노드는 메모리의 서로 다른 위치에 존재하며 다음 또는 이전 노드로 이동할 때 참조를 따라가야 한다.
    출처: https://www.scaler.com/topics/linked-list-in-java/

 

데이터 접근 속도

  • ArrayList
    인덱스를 통해 직접 요소에 접근하기 때문에 O(1) 시간복잡도를 가지므로 빠르다.
    하지만, 배열의 크기가 부족해지면 새로운 배열을 할당하고 모든 데이터를 복사해야 하므로 데이터 추가 시 시간이 O(n)으로 느려질 수 있다.

  • LinkedList
    인덱스 기반 접근은 O(n) 시간 복잡도를 가지며 느리다. 처음부터 차례대로 노드를 따라가야 하기 때문이다.
    중간에 삽입 및 삭제가 빈번한 경우에는 노드의 참조만 조정하면 되므로 빠른 삽입/삭제가 가능하다 
    삽입/삭제에 O(1)의 시간이 걸리지만, 위치까지 접근하는 데 O(n)의 시간이 소요될 수 있다.

 

데이터의 삽입 및 삭제

  • ArrayList
    배열의 끝에 데이터를 추가할 때는 빠르게 추가할 수 있다. 하지만 배열이 꽉 찬 상태라면 새 배열을 할당하고 데이터를 복사해서 옮겨야 하므로 조금 더 느릴 수 있다.
    중간에서의 삽입 및 삭제는 해당 인덱스 이후의 모든 요소를 한 칸 씩 이동해야 하므로 느리다.
  • LinkedList
    연결된 노드의 참조만 변경하면 되기 때문에 삽입 및 삭제의 시간이 빠르다. 하지만 삽입하거나 삭제할 위치를 찾는 데는 느리다.

 

메모리 사용

  • ArrayList
    배열에 저장된 데이터 외에 추가 메모리가 필요하지 않다. 배열의 크기를 미리 할당하기 때문에 때때로 메모리 낭비가 있을 수 있다.
  • LinkedList
    각 요소가 추가적인 메모리(노드의 참조 값)를 필요로 하므로 메모리 사용량이 ArrayList보다 많다. 각 노드는 이전, 다음 노드를 가리키는 두 개의 참조를 가지고 있어, 데이터 외에 추가적인 메모리를 사용한다.

 

성능 비교 요약

기능 ArrayList LinkedList
인덱스 기반 요소 접근 O(1) (매우 빠름) O(n) (느림)
끝에 요소 추가 O(1) (단, 배열이 가득 차면 (n)) O(1)
중간에 추가/삭제 O(n) (모든 요소를 이동해야함) O(1) (참조만 변경, 위치를 찾을 때 O(n))
메모리 효율 비교적 효율 적 (크기 증가 시엔 비효율) 추가적인 메모리 사용 (노드의 참조)
빈번한 삽입/삭제 중간에서는 비효율적 중간에서 매우 효율적

 

 

정리

 

ArrayList

읽기/ 검색이 자주 발생하고, 리스트의 끝에 추가하는 경우 성능이 뛰어남, 연속된 메모리를 사용하여 메모리 접근 속도가 빠르다. 중간에서의 삽입 삭제가 많을 경우 성능이 떨어진다.

 

LinkedList

삽입/ 삭제가 자주 발생하는 상황에 적합하다. 중간에서의 삽입/삭제가 빠르지만 인덱스 기반으로 요소에 접근하는 속도가 느리다. 노드가 이전, 다음 노드를 참조하고 있기 때문에 추가적인 메모리 오버헤드가 발생한다.

'Java' 카테고리의 다른 글

JAVA 컴파일 과정  (2) 2024.12.02
JAVA Stack & Queue  (1) 2024.10.04
JAVA Array(배열)  (4) 2024.10.02
JAVA 변수  (1) 2024.09.19
JAVA 메모리 구조  (1) 2024.09.19