본문 바로가기
Old Posts/Java

[Java] ArrayList 사용법 및 예제

by A6K 2021. 5. 24.

ArrayList

자바 프로그램에서 데이터의 나열을 저장하기 위해서 List 인터페이스를 구현한 클래스를 사용한다. ArrayList는 List 인터페이스를 구현하는 리스트로 배열처럼 연속된 메모리 공간을 사용하며, 인덱스를 이용해서 특정위치의 데이터에 바로 접근할 수 있다. 한번 생성되면 크기가 변하지 않는 배열과는 달리 객체가 추가되면서 필요할 경우 자동으로 크기가 늘어나도록 내부적으로 구현되어 있다는게 ArrayList 클래스의 특징이다.

리스트 자료구조를 만들고 싶을 때, 가장 많이 사용되는 클래스다.

ArrayList 사용법

ArrayList 생성

import java.util.ArrayList;

자바는 java.util.ArrayList 클래스를 통해 ArrayList를 제공하고 있다. ArrayList를 사용할 클래스에 java.util.ArrayList 클래스를 import 해준다.

ArrayList<String> list1 = new ArrayList<String>(); // 타입 지정
ArrayList<String> list2 = new ArrayList<>(); // 타입 추론 가능
ArrayList<String> list3 = new ArrayList<String>(100); // 초기 용량 지정
ArrayList<String> list4 = new ArrayList<String>(otherList); // 다른 컬렉션(Collection) 객체로부터 초기화

우선 ArrayList를 사용하려면 어떤 타입의 데이터를 다룰 것인지 '지네릭스(Generics)'를 통해서 데이터 타입을 명시해야한다. 위 예제에서는 String 타입의 데이터를 다루는 ArrayList 객체를 생성하는 예제들이다. 꺽쇠 문자( '<', '>' ) 사이에는 ArrayList가 다룰 클래스 이름이 들어간다. 만약 기본형(Primitive Type) 데이터를 저장하고자 할 때에는 래퍼 클래스(Wrapper Class)를 지네릭스에 써줘야한다. (참고 : [Java] 오토박싱(Auto Boxing)과 래퍼 클래스(Wrapper Class)

ArrayList는 데이터가 추가되면서 자동으로 용량(Capacity)을 늘려준다. 처음 데이터가 추가될 때 10개의 데이터를 저장할 수 있도록 초기 용량이 지정되며, 11번째 데이터가 추가되면 내부 배열의 사이즈를 훨씬 큰 값으로 다시 할당한 다음 기존 데이터를 복사해준다. 이런 동작은 사용하는데에는 편하지만 중간중간 기존 데이터가 새로운 내부 배열로 복사되는 오버헤드(Overhead)를 가지고 있다. 사용될 데이터의 개수를 미리 알고 있는 경우라면 애초에 ArrayList를 만들 때부터 큰 값으로 만들어주면 된다. 그러면 중간중간 데이터가 복사하면서 발생하는 오버헤드를 피할 수 있어 성능저하를 방지할 수 있다. ArrayList는 생성자에 초기 용량을 받을 수 있다.

마지막으로 다른 Collection 객체로부터 ArrayList를 초기화하는 생성자도 제공한다. ArrayList를 인자로 받는 API를 사용하기 위해서 Collection 타입 변환이 필요할 때 많이 사용된다.

ArrayList 값 추가 - add() 메소드

ArrayList 클래스에는 값을 추가하기 위한 add() 메소드가 있다.

ArrayList<String> list = new ArrayList<String>();
list.add("Data"); // 데이터 추가
list.add(3, "Data3"); // 3번 위치에 값 추가

우선 그냥 list.add()를 호출하면 배열의 가장 마지막 부분에 값을 추가한다.

이 과정에서 새로 추가될 데이터를 저장할 공간이 없다면, 즉 내부 배열이 꽉차있다면 더 큰 사이즈의 새로운 배열을 생성하고 기존 값들을 새로운 배열로 복사하는 동작도 수행된다.

add() 메소드는 특정 인덱스에 값을 추가할 수 있도록 숫자를 받을 수 있다.

배열의 중간부분에 새로운 데이터를 끼워넣는 동작이다. 이 경우 입력한 위치에 새로운 데이터를 끼워넣고, 그 뒤에 있는 데이터는 모두 한칸씩 뒤로 밀려나게 된다. 한칸씩 데이터들을 뒤로 밀어내는 동작은 ArrayList의 사이즈가 커질 수록 비효율적이 된다. (O(n) 시간을 소모하게 된다.)

ArrayList 값 삭제 - remove(), clear() 메소드

ArrayList에서 값을 제거하려면 remove() 메소드를 사용하면 된다.

list.remove(1); // 1번 값을 제거
list.clear(); // ArrayList 비우기

remove() 메소드는 어떤 데이터를 지울지 인덱스를 받게 되어 있다.

remove(1)을 호출하면 1번 인덱스에 해당하는 데이터를 삭제한다. 이 때, 제거된 데이터 뒤쪽에 있는 항목들은 한칸씩 앞으로 땡겨지게 된다. add() 때와 마찬가지로 한칸씩 땡기는 동작이 오버헤드로 작용할 수 있다.

ArrayList를 비우려면 clear() 메소드를 사용하면된다.

ArrayList 값 확인 - get() 메소드

ArrayList에 저장되어 있는 특정 값을 확인하려면 get() 메소드를 이용하면 된다.

list.get(0); // 0번 인덱스에 해당하는 값을 확인

ArrayList 값 확인 - 전체 값 순회

ArrayList에 들어있는 모든 값을 순회하면서 접근하고 싶은 경우 for 문을 이용해 접근할 수 있다.

ArrayList<String> list;

...

// for 문을 통한 접근
for (String elem : list) {
  System.out.println(elem);
}

자바의 For each 구문을 이용해서 컬렉션의 각 항목들을 순회할 수 있다. ArrayList 역시 For each 구문을 이용해서 접근할 수 있다.

혹은 Iterator를 이용해서 순회할 수도 있다.

Iterator iter = list.iterator();
while (iter.hasNext()) {
  String elem = iter.next();
  System.out.println(elem);
}

ArrayList 값 검색

특정 값이 ArrayList에 있는지 확인하거나 있다면 몇 번째 인덱스에 존재하는지 찾는 검색 기능을 위한 메소드도 제공된다.

ArrayList<String> list = new ArrayList<String>(Arrays.asList("Data1", "Data2", "Data3"));

boolea isContained = list.contains("Data1"); // true 리턴
int index = list.indexOf("Data2"); // 1 반환.. 만약 값이 없으면 -1 리턴

contains() 메소드는 equals() 메소드를 이용해서 특정 객체가 ArrayList에 있는지 확인한다. 있으면 true를 리턴하고, 없으면 false를 리턴한다.

indexOf() 메소드는 마찬가지로 특정 값에 해당하는 객체가 ArrayList에 있는지 확인한다. 다만 true/false가 아닌 몇 번째 인덱스에 해당하는 값인지 숫자를 리턴한다. 만약 ArrayList에 값이 없다면 -1이 리턴된다.

댓글