- java Array vs ArrayList2023년 08월 19일
- 알쓸개잡
- 작성자
- 2023.08.19.:17
java 에서는 Array 와 ArrayList 는 컬렉션 데이터를 저장하는데 자주 사용되는 기본적인 데이터 구조이다. 모두 동일한 용도로 사용되지만 서로 다른 특성으로 인해 애플리케이션 성능과 유연성에 영향을 미치는 부분이 있다.
이번 포스팅에서는 자바의 Array 와 ArrayList 의 주요 기능 및 각각의 장단점과 두 구조를 변환하는 여러 기법을 소개한다.
Arrays
Array(배열) 동일 데이터 타입의 요소를 연속된 메모리 위치에 저장하는 [고정 크기]를 가지는 데이터 구조이다. 배열의 각 요소는 index 로 검색할 수 있으며 첫 번째 요소는 index 0 부터 시작한다.
- 배열은 항상 동일한 데이터 타입의 요소를 저장한다. 배열 타입은 초기화할 때 고정 사이즈로 선언된다.
- 각각의 요소들은 index 를 통해서만 액세스 할 수 있다. 배열의 요소에 액세스 할 수 있는 다른 방법은 없다.
- 배열의 크기는 항상 고정되어 있으며 변경할 수 없다. 배열 크기보다 더 많은 요소를 저장하기 위해서는 새 배열을 생성하고 이전 배열의 요소들을 새로운 배열에 복사해야 한다. 배열 크기 보다 더 많은 요소를 추가하려고 하는 경우 ArrayIndexOutOfBoundsException 이 발생한다.
// 배열 선언 및 초기화 int[] a = new int[4]; a[0] = 1; a[1] = 2; a[2] = 4; a[3] = 8; for(int i = 0; i < a.length; i++) { System.out.println(a[i]); } ========== 결과 1 2 4 8
변수 a array 는 아래와 같은 구조로 데이터가 저장된다.
a[0] a[1] a[2] a[3] 1 2 4 8 ArrayList
ArrayList는 자바 컬렉션 프레임워크에 속해 있으며 List 인터페이스를 구현한다. 배열과 달리 ArrayList 는 요소가 추가되거나 제거될 때 동적으로 늘어나거나 줄어들 수 있다.
ArrayList 는 여러 타입의 요소를 저장할 수 있지만 요소를 가져올 때 런타임에 ClassCastException 이 발생할 수 있으므로 대부분 권장하지는 않는다. 타입 안전성을 강화하기 위해 제너릭을 사용하여 ArrayList 를 선언한다.
List<Integer> a = new ArrayList<>(); a.add(1); a.add(2); a.add(4); a.add(8); =================== for(Integer i : a) { System.out.println(i); } ======== 결과 1 2 4 8 =================== ListIterator<Integer> listIterator = a.listIterator(); while (listIterator.hasNext()) { System.out.println(listIterator.next()); } ======== 결과 1 2 4 8 =================== a.forEach(System.out::println); ======== 결과 1 2 4 8
ArrayList 는 for-loop 을 사용하여 순차적으로 접근하는 방법 이외에도 ListIterator 와 같은 iterator 를 사용하여 각 요소에 접근하거나 forEach(Consumer<? super T> action) 을 통해서도 접근할 수 있다.
Array 와 ArrayList 비교
Array ArrayList 크기 초기화에 지정된 크기로 고정 동적으로 resize 됨 메모리 배열 크기가 요소의 수보다 큰 경우 낭비 초래 동적 크기 조정으로 약간의 성능 오버헤드 발생 성능 읽기 작업의 경우 인덱스를 사용하여 요소에 직접 액세스 하기 때문에 ArrayList 보다 빠르지만 크기 조정이 필요한 쓰기 작업의 경우 ArrayList 가 성능이 좋음 크기 조정이 필요한 쓰기 작업을 제외하고 ArrayList 는 배열보다 성능이 떨어짐 적합한 용도 고정된 크기의 컬렉션이 필요하고 메모리 효율이 중요한 경우에 사용 작고 미미한 성능 향상 보다 편의성이 우선시되는 소규모 컬렉션에 사용 Array 를 ArrayList 로 변환
샘플 코드는 JDK 17 로 작성되었습니다.
//mutable arraylist 로 변환 //arrayList 에 요소를 추가하거나 삭제할 수 있음 String[] sports = {"baseball", "soccer", "basketball"}; ArrayList<String> arrayList = new ArrayList<>(Arrays.asList(sports)); sportList.add("running"); sportList.forEach(System.out::println); //immutable arraylist 로 변환 String[] sports = {"baseball", "basketball", "soccer"}; List<String> sportList = Arrays.asList(sports); sportList.add("running"); // -> UnsupportedOperationException 발생 sportList.forEach(System.out::println);
java8 에 도입된 stream 을 사용하여 변환할 수 있습니다.
String[] sports = {"baseball", "basketball", "soccer"}; //immutable arraylist 로 변환 List<String> sportList = Arrays.stream(sports).toList(); sportList.forEach(System.out::println);
ArrayList 를 Array 로 변환
ArrayList 의 toArray 를 통해 변환한다.
List<String> arrayList = Arrays.asList("baseball", "basketball", "soccer"); //방법1 String[] array1 = arrayList.toArray(new String[0]); //방법2 Object[] array2 = arrayList.toArray(); //방법3 String[] array3 = arrayList.toArray(new String[4]);
방법1은 요소가 없는 빈 String 배열을 파라미터로 넘겨주어 String[] 로 변환하였다. new String[0] 을 인자로 넘겨준 이유는 빈 배열 타입을 생성하도록 하여 메모리를 절감하기 위해서이다. new String[arrayList.size()] 를 넘기지 않는 이유는 불필요한 메모리 사용 때문이다. 즉, new String[0] 을 넘기나 new String[arrayList.size()] 를 넘기나 toArray 의 결과는 동일하다.
방법2는 아무런 파라미터도 넘기지 않으나 Object[] 이 리턴되기 때문에 형변환을 해줘야 한다.
방법3은 ArrayList 보다 사이즈가 큰 배열을 파라미터로 넘겼을 때 ArrayList 의 각 요소는 배열에 복사되지만 ArrayList 보다 더 큰 index 의 값에는 null 이 채워짐을 보여주기 위해서 추가하였다.
지금까지 Array와 ArrayList 에 대해서 알아 보았다.
이 포스팅을 읽으시는 분에게 도움이 되었기를 바랍니다.
'자바' 카테고리의 다른 글
jdk pattern matching for instanceof (0) 2023.08.26 java switch expression - from jdk 14 (0) 2023.08.20 java record 용법 - from jdk 14 (0) 2023.08.19 CompletableFuture 를 알아보자 (0) 2023.08.06 byte 배열에서 charset 정보 detecting 하기 (0) 2023.08.04 다음글이전글이전 글이 없습니다.댓글