지금까지 List를 생성할 때 대부분 new ArrayList<>()를 사용했었다.
회사에서 다른 분들의 코드를 보다가 Arrays.asList()를 이용한 부분이 있었고 참고해서 사용했는데, 차이점을 정확히 알고 싶어 정리하고자 한다.
1. 다른 class, 다른 return type
- 다른 class : new ArrayList<>()와 Arrays.asList()는 다음과 같이 class가 다르다.
// new ArrayList<>()
import java.util.ArrayList;
// Arrays.asList()
import java.util.Arrays;
- new ArrayList<>()는 ArrayList를 Arrays.asList()는 Arrays의 정적 클래스인 ArrayList를 리턴한다.
- 아래는 Arrays 클래스의 asList이다.
// Arrays.class
@SafeVarargs
public static <T> List<T> asList(T... a) {
return new Arrays.ArrayList(a);
}
2. 원소의 추가/삭제 가능 여부
결론부터 정리하면 다음과 같다.
원소의 추가/삭제 | set 사용 | |
new ArrayList<>() | 가능 | 가능 |
Arrays.asList() | 불가능 | 가능 |
2-1. new ArrayList<>()부터 먼저 정리해보자.
import java.util.ArrayList;
public class ArrayListTest {
public static void main(String[] args) {
// ArrayList 생성
ArrayList<String> fruits = new ArrayList<>();
// add() method로 원소 추가
fruits.add("Apple");
fruits.add("Banana");
fruits.add(0, "Mango");
fruits.add("Strawberry");
// set() method로 특정 인덱스의 값을 대체
fruits.set(0, "Melon");
System.out.println(fruits); // [Melon, Apple, Banana, Strawberry]
}
}
add() 메서드는 기본적으로 리스트의 가장 끝에 원소를 추가한다.
별도로 인덱스를 지정하면 해당 인덱스에 값이 추가되고 이후의 인덱스에 있는 값들은 한 칸씩 밀린다.
다시 하나씩 살펴보면 Apple과 Banana가 ArrayList fruits에 순서대로 추가된다.
Mango가 0번째 인덱스에 추가되면서 Apple과 Banana는 각각 인덱스 한 칸씩 밀리게 된다.
그리고 Strawberry가 맨 뒤에 추가된다.
마지막으로 특정 인덱스의 값을 대체하는 set() 메서드를 통해 0번째 인덱스에 있는 Mango가 Melon으로 변경된다.
2-2. Arrays.asList()에 대해 정리해보자.
Arrays.asList()는 javadoc 와 클래스에서 메서드 설명을 찾아보면 다음과 같은 내용을 찾을 수 있다.
Returns a fixed-size list backed by the specified array.
해석해보면 특정한 배열에 의해 백업된 고정된 크기의 List를 반환한다는 내용이다.
말 그대로 Arrays.asList()는 고정된 List로 원소를 추가하거나 삭제할 수 없다.
하지만 List의 원소 값을 변경할 수는 있다.
원소 값 변경 방법에는 2가지가 있다.
2-2-1. set() 메서드 사용
set() 메서드를 통해 특정 인덱스의 원소 값을 변경할 수 있다.
import java.util.ArrayList;
import java.util.Arrays;
public class ArrayAsListTest {
public static void main(String[] args) {
String[] fruits = {"Apple", "Banana", "Mango"};
List<String> list = Arrays.asList(fruits);
System.out.println(list); // [Apple, Banana, Mango]
System.out.println(fruits); // [Apple, Banana, Mango]
list.set(2, "Melon"); // set() method로 두 번째 인덱스 값 변경
System.out.println(list); // [Apple, Banana, Melon]
System.out.println(fruits); // [Apple, Banana, Melon]
}
}
set() 메서드를 이용해 두 번째 인덱스의 원소를 변경했다.
list에 담겨있는 두 번째 인덱스의 원소를 변경했는데 원본 배열인 fruits의 데이터도 함께 변경되었다.
List는 내부 구조가 배열로 만들어져 있어 asList()를 사용해서 반환되는 List도 배열을 갖게 된다.
이 때, asList()를 사용해 List 객체를 만들 때 새로운 배열 객체를 만드는 것이 아니라, 원본 배열의 주소값을 가져오게 된다.
따라서 asList()를 사용해서 내용을 수정하면 원본 배열도 함께 수정된다.
2-2-2. 원본 배열 변경
import java.util.ArrayList;
import java.util.Arrays;
public class ArrayAsListTest {
public static void main(String[] args) {
String[] fruits = {"Apple", "Banana", "Mango"};
List<String> list = Arrays.asList(fruits);
System.out.println(list); // [Apple, Banana, Mango]
System.out.println(fruits); // [Apple, Banana, Mango]
fruits[2] = "Melon"; // 원본 배열 fruits의 두 번째 인덱스 값 변경
System.out.println(list); // [Apple, Banana, Melon]
System.out.println(fruits); // [Apple, Banana, Melon]
}
}
두 번째 방법은 원본 배열인 String[] fruits 배열을 변경시키는 방법이다.
Arrays.asList()는 String[] fruits(특정한 배열)를 백업할 때 주소값을 가져온다.
따라서 위와 같이 String[] fruits가 변경되면 list도 변경된다.(참고로 new ArrayList<>()를 사용하면 새로운 주소값를 할당한다.)
만약 원소를 추가/삭제하고 싶다면 new ArrayList로 변환해준 뒤 add() 메서드를 사용하면 된다.
import java.util.ArrayList;
import java.util.Arrays;
public class ArrayAsListTest {
public static void main(String[] args) {
String[] fruits = {"Apple", "Banana", "Mango"};
List<String> arrayList = new ArrayList<>(Arrays.asList(fruits));
arrayList.add("Melon");
System.out.println(arrayList); // [Apple, Banana, Mango, Melon]
}
}
다음과 같이 ArrayList 생성자는 java.util.Arrays.ArrayList의 상위 클래스인 Collection type도 받아들일 수 있기 때문에 가능하다.
new ArrayList<>()와 Arrays.asList()에 대해서 조금은 정리가 된 것 같다.
마지막으로 간단히 정리를 해보자면
new ArrayList<>() : 원본 배열의 데이터가 변경되면 안되거나 새로운 주소값으로 할당해야할 때
Arrays.asList() : 원소의 개수가 제한되어 사용되어야 하거나, 변할 필요가 없을 때
이렇게 구분해 사용하면 좋을 것 같다.
'Java' 카테고리의 다른 글
[Java] 코드 특정 구간의 실행 시간 구하기 (0) | 2023.06.14 |
---|---|
[Java] HashMap에 특정 key가 존재하는지 확인하기 (0) | 2023.04.17 |
[Java] HashMap과 HashSet의 차이 (0) | 2022.12.23 |
[Java] 제어자(modifier) (2) - 접근 제어자, 그 외 제어자 (0) | 2022.08.06 |
[Java] 제어자(modifier) (1) - 접근 제어자, 그 외 제어자( + 추상클래스와 인터페이스) (0) | 2022.08.06 |