배열을 사용하기 전에 크기를 먼저 선언해야 하는 것이 불편하다고 느껴진 적이 있나요? 값을 추가하기 전에 배열이 저장할 데이터의 개수를 미리 정해야 한다는 점은 생각보다 번거로운 일입니다. 이런 고민을 해결해 주는 강력한 도구가 바로 자바의 ArrayList입니다.
이 글에서는 ArrayList가 무엇인지, 어떤 원리로 작동하는지, 그리고 기존 배열과 어떻게 다른지 살펴봅니다. 아울러 ArrayList 클래스를 효과적으로 다루기 위해 꼭 알아야 할 핵심 메서드들도 예제 코드와 함께 정리했습니다. 그럼 시작해 보겠습니다!
ArrayList란 무엇인가?
ArrayList는 크기를 자유롭게 조절할 수 있는 배열(resizable array)을 만들 수 있게 해주는 특별한 리스트입니다. ArrayList 클래스는 순서가 있는 데이터를 저장하는 데 사용되는 List 인터페이스를 구현합니다.
자바에서 일반 배열을 사용할 때는 값을 저장하기 전에 반드시 배열의 크기를 선언해야 합니다. 하지만 실제 개발에서는 배열을 선언하는 시점에 몇 개의 값을 저장하게 될지 알 수 없는 경우가 많습니다. 이것이 바로 문제가 되는 부분입니다.
ArrayList 클래스를 사용하면 저장 용량을 미리 지정하지 않아도 되는 배열을 만들 수 있습니다. 흔히 동적 배열(dynamic array)이라고 불리는 ArrayList는 요소를 추가하거나 삭제할 때마다 필요에 따라 용량이 자동으로 조절됩니다.
ArrayList 생성 방법
가장 기본적인 단계인 ArrayList 선언부터 시작해 보겠습니다. ArrayList는 List 인터페이스를 기반으로 동작하기 때문에 일반 배열을 선언하는 방식과는 차이가 있습니다.
자바 파일을 열고 메인 클래스에 다음 코드를 입력합니다:
import java.util.ArrayList; ArrayList<String> songs = new ArrayList<>();
위 코드는 songs라는 이름의 ArrayList를 생성합니다. 여기서 String은 리스트에 저장할 데이터의 타입을 의미하고, ArrayList는 생성하려는 객체의 타입을 나타냅니다.
ArrayList는 자바의 util 라이브러리에 포함되어 있으므로, 코드에서 사용하려면 반드시 import 문으로 가져와야 합니다.
주의할 점은 ArrayList를 생성할 때 원시 타입(primitive type)을 직접 사용할 수 없다는 것입니다. 예를 들어 정수형 리스트를 만들고 싶다면 원시 타입인 int 대신 Integer 래퍼 클래스를 사용해야 합니다.
또한 위 코드에서 ArrayList가 저장할 값의 개수를 지정하지 않았다는 점에 주목하세요. ArrayList는 동적으로 크기가 조절되기 때문에 별도의 크기 선언이 필요 없습니다.
ArrayList에 요소 추가하기
add() 메서드를 사용하면 리스트에 요소를 하나씩 추가할 수 있습니다. 비틀스(The Beatles)의 노래 두 곡, 'Love Me Do'와 'Help!'를 songs 리스트에 추가한다고 가정해 보겠습니다.
import java.util.ArrayList;
class Main {
public static void main(String[] args) {
ArrayList<String> songs = new ArrayList<>();
songs.add("Love Me Do");
songs.add("Help!");
System.out.println("Songs: " + songs);
}
}
실행 결과:
Songs: [Love Me Do, Help!]
일반 배열과 마찬가지로 ArrayList의 각 요소에는 고유한 인덱스 번호가 부여됩니다. ArrayList는 순서가 있는 자료구조이며, 인덱스는 프로그램에게 각 항목이 어떤 순서로 배치되어야 하는지 알려줍니다. 필요하다면 요소를 추가할 인덱스 위치를 직접 지정할 수도 있습니다:
songs.add(0, "Love Me Do");
이 코드는 'Love Me Do'를 songs 리스트의 0번 인덱스 위치에 삽입합니다.
ArrayList 초기화하기
일반 배열을 선언할 때는 값을 함께 나열하여 배열을 즉시 초기화할 수 있습니다. 하지만 ArrayList는 이런 방식을 지원하지 않습니다. 대신 Arrays 클래스의 asList() 메서드를 사용해야 합니다. asList()는 배열을 리스트 형태로 반환하며, 이를 통해 ArrayList를 초기화할 수 있습니다.
이미 추가할 값들이 정해져 있다면, 리스트를 선언과 동시에 초기화하는 것이 편리합니다.
for 반복문으로 각 항목을 하나씩 추가하는 방법도 있지만, asList()를 사용한 초기화가 더 간결하고 효율적입니다.
먼저 코드에서 사용할 라이브러리를 import 합니다:
import java.util.ArrayList; import java.util.Arrays;
그다음 두 개의 기본값으로 songs ArrayList를 초기화하는 클래스를 작성합니다:
class Main {
public static void main(String[] args) {
ArrayList<String> songs = new ArrayList(Arrays.asList("Love Me Do", "Help!"));
System.out.println("Songs: " + songs);
}
}
이 코드는 문자열을 저장할 수 있는 ArrayList를 선언하고, asList()를 사용해 앞선 예제에서 추가했던 것과 같은 비틀스의 노래 두 곡을 기본값으로 초기화합니다.
ArrayList에서 요소 가져오기
ArrayList 클래스는 리스트의 요소에 접근할 수 있는 유용한 get() 메서드를 제공합니다. 이 메서드를 사용하려면 접근하려는 요소의 인덱스 위치를 지정해야 합니다.
import java.util.ArrayList;
class Main {
public static void main(String[] args) {
ArrayList<String> songs = new ArrayList<>();
songs.add("Love Me Do");
songs.add("Help!");
System.out.println("Second song: " + songs.get(1));
}
}
이 코드는 ArrayList를 생성하고 두 개의 값을 추가한 뒤, songs.get(1)을 사용해 인덱스 1에 있는 노래를 가져옵니다. 실행 결과는 다음과 같습니다:
Second song: Help!
ArrayList 값 수정하기
ArrayList의 값을 변경하는 것은 요소를 추가하는 것만큼 쉽습니다. 내장 메서드인 set()을 사용하면 리스트에 저장된 값을 바꿀 수 있습니다.
import java.util.ArrayList;
class Main {
public static void main(String[] args) {
ArrayList<String> songs = new ArrayList<>();
songs.add("Love Me Do");
songs.add("Help!");
System.out.println("Songs: " + songs);
songs.set(1, "Come Together");
System.out.println("Songs: " + songs);
}
}
실행 결과:
Songs: [Love Me Do, Help!] Songs: [Love Me Do, Come Together]
위 코드는 리스트에 'Love Me Do'와 'Help!' 두 값을 추가한 후, set() 메서드로 인덱스 1의 항목을 'Come Together'로 변경합니다. 그 결과 'Help!'가 'Come Together'로 교체되었고, 프로그램 마지막에 리스트를 출력하면 변경된 내용을 확인할 수 있습니다.
ArrayList에서 요소 삭제하기
요소를 영원히 ArrayList에 남겨둘 필요는 없습니다. remove() 메서드를 사용하면 언제든지 요소를 삭제할 수 있습니다. 메서드 이름도 직관적이라 기억하기 쉽습니다.
import java.util.ArrayList;
class Main {
public static void main(String[] args) {
ArrayList<String> songs = new ArrayList<>();
songs.add("Love Me Do");
songs.add("Help!");
System.out.println("Songs: " + songs);
String removed = songs.remove(0);
System.out.println("Songs: " + songs);
System.out.println(removed);
}
}
이 예제에서는 리스트에 두 개의 항목을 추가한 뒤, 인덱스 0에 있는 항목을 삭제합니다. 실행 결과는 다음과 같습니다:
Songs: [Love Me Do, Help!] Songs: [Help!] Love Me Do
'Love Me Do'가 리스트에서 성공적으로 삭제되었습니다. remove() 메서드는 삭제된 항목을 반환하며, 이 예제에서는 반환값을 removed 변수에 저장한 후 콘솔에 출력했습니다.
ArrayList 순회하기
ArrayList의 모든 요소를 하나씩 처리하고 싶다면 어떻게 해야 할까요? for 반복문 또는 for-each 반복문을 사용하면 됩니다. 두 방식 모두 널리 사용되며, 상황에 따라 선택하면 됩니다.
예를 들어 리스트에 있는 모든 비틀스의 노래를 한 줄씩 콘솔에 출력한다고 가정해 보겠습니다. 다음 코드를 사용할 수 있습니다:
import java.util.ArrayList;
class Main {
public static void main(String[] args) {
ArrayList<String> songs = new ArrayList<>();
songs.add("Love Me Do");
songs.add("Help!");
for (int i = 0; i < songs.size(); i++) {
System.out.println(songs.get(i));
}
}
}
이 프로그램은 for 반복문을 사용해 ArrayList의 모든 항목을 순회하며, 각 항목을 콘솔에 한 줄씩 출력합니다. 리스트의 모든 항목이 출력될 때까지 반복이 계속됩니다.
여기서 songs.size() 메서드가 사용된 점에 주목하세요. size() 메서드는 ArrayList에 저장된 값의 개수를 알려줍니다.
실행 결과:
Love Me Do Help!
마찬가지로 for-each 반복문으로도 ArrayList를 순회할 수 있습니다. for-each 반복문은 반복 가능한(iterable) 모든 객체를 순회할 수 있기 때문입니다. 다음 예제를 살펴보세요:
import java.util.ArrayList;
class Main {
public static void main(String[] args) {
ArrayList<String> songs = new ArrayList<>();
songs.add("Love Me Do");
songs.add("Help!");
for (String song : songs) {
System.out.println(song);
}
}
}
이 프로그램은 구조와 목적 면에서 앞선 예제와 거의 같으며, songs 리스트의 모든 값을 콘솔에 출력합니다. 차이점은 for-each 반복문을 사용해 각 값을 순회했다는 것입니다.
for-each 반복문은 코드가 더 읽기 쉬워 가독성 면에서 장점이 있지만, 두 방식 모두 효과적으로 동작합니다.
마무리
자바의 ArrayList 클래스를 사용하면 저장할 값의 개수를 미리 지정하지 않고도 여러 값을 담을 수 있는 배열을 만들 수 있습니다.
이 글에서는 ArrayList의 기본적인 사용법만 다루었습니다. 더 깊이 학습하고 싶다면 다음 주제들을 참고해 보세요:
- ArrayList를 배열로 변환하는 방법
- ArrayList를 초기화하는 다양한 방법
- ArrayList를 정렬하는 방법
이제 배열에 몇 개의 값을 저장해야 할지 미리 알지 못해도 걱정할 필요가 없습니다. ArrayList를 활용하면 이 문제를 손쉽게 해결할 수 있습니다!