ArrayList는 자바에서 가장 널리 사용되는 컬렉션 중 하나로, 가변 크기의 배열을 구현한 클래스입니다. 이는 배열과 비슷한 특성을 가지지만, 데이터의 동적 추가와 제거가 가능하다는 점에서 큰 장점을 지닙니다. 이 글에서는 ArrayList의 구조와 특성, 장단점, 사용 예제 등을 자세하게 다루어, 여러분이 ArrayList를 제대로 이해하고 활용할 수 있도록 도와드리겠습니다.
ArrayList는 자바의 java.util 패키지에 포함된 클래스로, 배열의 단점을 보완하여 더 유연하게 데이터를 관리할 수 있도록 도와줍니다. 기본 배열(array)은 생성 시 크기가 고정되며, 변경이 불가능한 반면 ArrayList는 크기가 자동으로 조정되어 데이터를 추가하거나 삭제할 수 있습니다. 이로 인해 ArrayList는 요소의 개수가 동적으로 변할 수 있는 상황에서 매우 유용하게 사용됩니다.
ArrayList는 내부적으로 배열을 사용하여 데이터를 관리합니다. 기본적으로 ArrayList의 초기 용량은 10이며, 만약 추가적인 요소를 저장해야 할 때 용량을 초과하게 되면, 내부 배열의 크기가 1.5배로 증가하게 됩니다. 이는 ensureCapacity()라는 메서드를 통해 이루어지며, 이 과정에서 새로운 배열이 생성되고 기존 요소들이 새로운 배열로 복사됩니다. 따라서 크기 조정이 자주 일어나면 성능 저하가 발생할 수 있습니다.
ArrayList<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Cherry");
Java위 코드에서 요소가 추가될 때마다 내부 배열의 크기가 적절히 조절되며, 이는 사용자가 명시적으로 크기를 관리할 필요 없이 동적으로 관리됩니다.
list.trimToSize();
Java이 메서드는 리스트의 크기를 현재 요소의 수에 맞게 조정하여 불필요한 메모리를 줄이는 데 유용합니다.
ArrayList에 요소를 추가하는 가장 기본적인 메서드는 add()입니다. 이 메서드는 끝에 새로운 요소를 추가하며, 시간 복잡도는 평균적으로 O(1)입니다. 다만, 내부 배열의 크기를 변경해야 하는 상황에서는 O(n)의 복잡도를 가지게 됩니다.
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
Java특정 위치에 요소를 추가할 수도 있습니다. 이 경우 해당 인덱스 이후의 모든 요소들이 한 칸씩 뒤로 이동해야 하기 때문에 시간 복잡도는 O(n)입니다.
numbers.add(1, 10); // 인덱스 1에 값 10을 추가
Javaget() 메서드를 사용하면 인덱스를 통해 특정 요소에 접근할 수 있습니다. 이는 배열처럼 O(1)의 시간 복잡도를 가지며, 빠르게 원하는 요소를 검색할 수 있습니다.
int number = numbers.get(1); // 결과: 10
Java특정 위치의 요소를 수정할 수 있습니다. 이는 O(1)의 시간 복잡도를 가지며, 요소의 값을 직접 변경합니다.
numbers.set(1, 20); // 인덱스 1의 값을 20으로 변경
Javaremove() 메서드는 특정 인덱스에 있는 요소를 제거하거나 특정 값을 가진 첫 번째 요소를 제거합니다. 이 경우 요소를 제거한 뒤 나머지 요소들을 앞으로 이동시키기 때문에, 최악의 경우 O(n)의 시간 복잡도를 가집니다.
numbers.remove(1); // 인덱스 1의 요소(20)를 제거
Java리스트에 포함된 요소의 수를 반환하는 size() 메서드는 O(1)의 시간 복잡도를 가집니다.
int size = numbers.size(); // 현재 리스트 크기 반환
Java모든 요소를 제거하고 리스트를 비웁니다. 시간 복잡도는 O(n)이며, 요소들을 한 번에 제거합니다.
numbers.clear(); // 모든 요소 제거
JavaArrayList와 LinkedList는 둘 다 List 인터페이스를 구현하고 있지만, 내부 구조와 특성에서 차이가 있습니다. ArrayList는 검색 속도가 빠르지만 삽입/삭제에 비효율적입니다. 반면 LinkedList는 삽입/삭제가 빠르지만 인덱스를 통한 접근이 느립니다. 따라서 읽기 작업이 많은 경우에는 ArrayList를, 삽입/삭제 작업이 빈번한 경우에는 LinkedList를 사용하는 것이 좋습니다.
특징 | ArrayList | LinkedList |
---|---|---|
내부 구조 | 동적 배열 | 이중 연결 리스트 |
접근 속도 | O(1) (인덱스) | O(n) |
삽입/삭제 속도 | O(n) | O(1) (앞뒤에서) |
메모리 사용 | 효율적 | 추가적인 노드 오버헤드 |
다음은 ArrayList를 사용하여 학생들의 이름을 관리하는 간단한 예제입니다.
import java.util.ArrayList;
public class StudentList {
public static void main(String[] args) {
ArrayList<String> students = new ArrayList<>();
students.add("Minsu");
students.add("Jihyun");
students.add("Soyeon");
// 학생 목록 출력
for (String student : students) {
System.out.println(student);
}
// 학생 제거
students.remove("Jihyun");
// 학생 목록 출력 (업데이트 후)
System.out.println("\n업데이트된 학생 목록:");
for (String student : students) {
System.out.println(student);
}
}
}
Java위 코드에서 ArrayList는 학생들의 이름을 동적으로 관리하는 데 사용됩니다. 요소를 추가하고 제거하는 작업이 간단하게 이루어지며, 리스트의 크기도 자동으로 조절됩니다.
ArrayList는 자바에서 매우 유용한 자료구조로, 동적 크기 조절과 빠른 요소 접근의 장점을 가지고 있습니다. 하지만 삽입/삭제 작업에서는 성능 저하가 발생할 수 있기 때문에, 사용 상황에 따라 적절한 리스트 타입을 선택하는 것이 중요합니다. ArrayList는 읽기 작업이 빈번한 경우에 특히 유용하며, 자바 개발 시 가장 많이 사용되는 컬렉션 중 하나입니다.
ArrayList를 제대로 이해하고 사용하는 것은 자바 프로그래밍에서 매우 중요한 요소입니다. 위에서 설명한 개념과 내부 동작 원리를 잘 이해하고 나면, ArrayList를 적절히 활용하여 다양한 상황에서 효율적으로 데이터를 관리할 수 있을 것입니다.
추가적으로, ArrayList를 사용하는 멀티스레드 환경에서의 주의 사항과 성능 최적화 전략을 고려하여, 프로그램의 요구사항에 맞는 적절한 자료구조를 선택하는 것이 중요합니다.
제네릭(Generic)이란? 자바 제네릭은 코드의 재사용성을 높이고 타입 안전성을 보장하는 중요한 개념입니다. 이 블로그 글에서는 자바…
예외란 무엇인가? 자바에서 예외(Exception)는 프로그램 실행 중에 발생하는 비정상적인 상황을 나타냅니다. 즉, 정상적인 프로그램 흐름에서…
중첩클래스란? 자바에서 중첩 클래스(Nested Class)는 자바 프로그래밍의 중요한 개념 중 하나로, 클래스 안에 다른 클래스를…
Enum이란? Enum은 "enumeration"의 줄임말로, 특정 값들의 집합을 정의할 수 있는 특별한 클래스입니다. 예를 들어, 요일,…
래퍼 클래스(Wrapper Class)란? 자바에서 래퍼 클래스는 기본 데이터 타입(Primitive Data Type)을 객체(Object)로 감싸는 클래스입니다. 자바의…
서론 Java에서 문자열을 다룰 때, 문자열의 변경이 빈번하게 발생하는 경우라면 StringBuilder 클래스를 사용하는 것이 매우…