-
너무 다양한 List를 만드는 방법들..언어/자바 2023. 12. 20. 01:27
자바스크립트에서 "[]"로 정적 배열 개념없이 동적 배열만 사용해온 나에게 자바는 너무 다양한 List를 생성하는 방법을 가진 것이 아닌가라는 생각이 든다.
Q.그래서 배열이 필요하면 난 무엇을 사용해야되나?
우선 내 머릿속에 있는 List와 배열의 개념부터 명확하게 할 필요가 있다.
기존에 자바스크립트에 '배열'이란 단어로 퉁치고 있던 "동일한 타입의 목록"을 재정의하자.1. new int[size]
작은 개념에서 부터 시작하자.
자바에서 배열은 정적 배열을 이야기한다. ( 배열 == 정적 배열 )int[] arr = new int[3]; arr[0] = 0; arr[1] = 1; arr[2] = 2 arr[3] = 3; // error int[] arr2 = { 1, 2 };
사이즈가 정해져있다. 그래서 여러모로 데이터를 삽입하는 과정에서 불편함을 느낀다.
사이즈를 2배씩 늘려주고 뭐 이런 이야기는 다른 글에서 하는걸로2. list.toArray()
잘 쓰이지는 않을 것 같지만 List의 인스턴스를 다시 배열로 바꾸는 방법도 있다.
toArray()는 인자를 전달하지 않는 경우 Object[]을 반환하는 것에 주의해야할 것 같다.List<String> list = new ArrayList<>(); list.add("a"); list.add("b"); Object[] arr = list.toArray(); arr.length // 2 String[] sArr = list.toArray(new String[0]); // 0을 넣으면 list의 길이만큼 sArr.length // 2 String[] sArr = list.toArray(new String[10]); // 인자에서 길이와 타입을 조절 sArr.length // 10
Q.그럼 List는 무엇?
기본적으로 List는 배열에 각종 추가 기능들을 api로 제공하는 자료구조라고 1차적으로 이해할 수 있겠다. 보다 편리하게 배열을 사용할 수 있도록 Wrapping 되어있는 형태.
3. Arrays.asList()
as라는 단어를 보면 casting이 떠오른다.
Arrays.asList는 "Array를 List로 casting 하겠다" 라고 이해하도록 해보겠다.
(근본은 array이지만 list의 api를 사용할 수 있는 상태)Integer[] arr = {1, 2, 3}; arr[0] // 1 List<Integer> list = Arrays.asList(arr); list.get(0) // 1 // 리스트가 제공하는 api사용 가능! arr[0] = 100 list.get(0) // 100 // 복사가 아닌 참조만 하고 있음 list.set(0, 50) list.get(0) // 50 // 사이즈 변경없이 요소는 변경이 가능
기존에 배열에서는 [idx]를 사용해서 배열의 요소에 접근했는데, 이제는 get메소드를 사용할 수 있게 되었다. get 뿐만아니라 stream 등 다양한 list의 api 사용이 가능하다.
하지만 Array를 List로 casting 했을 뿐이기에 아직 Array가 가지는 한계는 그대로이다.
Integer[] arr = {1, 2, 3}; List<Integer> list = Arrays.asList(arr); list.add(100) // java.lang.UnsupportedOperationException
위에서 언급했듯이, "배열"은 사이즈를 동적으로 변경할 수 없다. 따라서 사이즈가 3으로 처음에 설정된 상태에서 4번째 인자를 add로 추가하면 UnsupportedOperationException가 발생한다.
또 다른 이상한 동작으로는
int[] arr = {1, 2, 3}; List<int[]> list = Arrays.asList(arr); list.get(0) // arr의 주소값 list.get(0)[0] // 1 char[] cArr = {'a', 'b', 'c'}; List<char[]> cList = Arrays.asList(cArr); cList.get(0) // cArr의 주소값 cList.get(0)[0] // 'a'
Integer가 인자인 배열을 Array.asList에 넣을 경우 List가 반환되지만,
int가 인자인 배열을 넣을 경우 List<int[]>가 반환된다!?가변인자 이것은 asList(T...args) 가변인자를 사용하기 때문에 발생한다. 가변인자를 사용하면 args는 T 타입의 배열이 된다. 자바가 내부적으로 배열을 생성하기 때문에 성능 이슈가 생길 수 있고 오버라이드와 함께 사용하지 않는 것이 좋다.
자바가 가변인자를 사용하는 경우 원시형[]은 그 자체를 T 타입으로 결정한다.
따라서, int[] 을 인자로 넣는다면 자바가 T = int[ ]로 결정하고 args는 int[ ][ ]가 되기때문에 List<int[]>을 써야하는 것이다.
반대로 참조형[]인 Integer[]의 경우는, 자바가 T = Integer로 결정하고 args는 Integer[]이 되기 때문에 List를 사용할 수 있는 것이다.자바에서 이렇게 하기로 한 부분이니까 외워야하는 부분!
4. List.of()
위의 2가지 예제와는 다르게, List.of는 바로 List를 생성해준다. (자바9 도입)
하지만 사이즈와 요소 수정이 불가능한 List를 만들어준다.List.of(1,2,3); // get은 가능하지만 사이즈, 요소 둘 다 변경이 불가능 list.get(0) // 1 list.add(100) // UnsupportedOperationException list.set(0, 10) // UnsupportedOperationException // Collections.unmodifiable() 을 사용해서 같은 효과를 낼 수 있다. Integer[] arr = {1, 2, 3}; List<Integer> list = Arrays.asList(arr); List<Integer> unmodifiable = Collections.unmodifiableList(list); unmodifiable.set(0, 12); // UnsupportedOperationException
어디다 쓸까? stream으로 만들어서 사용가능
List<Integer> list = List.of(1,2,3); List<Integer> newList = list.stream().map((i) -> { return i * 2; }).collect(Collectors.toList()); newList.get(0); // 2 newList.set(0, 10); // 새로운 배열은 수정이 가능하다. newList.get(0); // 10 list.set(0, 11); // UnsupportedOperationException
Q. List도 사이즈 조절은 못하나?
5. new ArrayList<>()
동적배열이자 사이즈 조절이 가능한 List를 생성하는 방법이다.
지금까지 언급된 형태 중에 가장 자유로운 형태이다.List<String> list = new ArrayList<>(); list.add("A"); list.add("B"); list.set(0,"C"); list.get(0); // 모든 동작이 에러없이 실행
위의 List들과 마찬가지로 stream으로 변경, 혹은 unmodifiable하게 수정도 가능하다.
Sumamry
- 배열
- 자바에서 배열과 List는 다르다.
- 배열은 사이즈를 조절할 수 없는 정적 배열이다.
- new int[size] 혹은 list.toArray(new Integer[size]) 로 만든다.
2. List
- 정적 배열과 동적 배열을 모두 포함하는 개념이다.
- 기본적으로 배열 + 편의api = List라고 생각할 수 있다.
- Array.asList(), List.of(), new ArrayList()를 사용해서 만들 수 있다.
- ArrayList의 경우에는 배열의 사이즈를 수정할 수 있는 동적 배열을 만든다.
끝
'언어 > 자바' 카테고리의 다른 글
Java I/O <2 - InputStream> (0) 2023.12.23 Java I/O <1 - OutputStream> (0) 2023.12.23 Queue의 add와 offer의 차이 (0) 2023.12.20 instanceof는 어떻게 작동하나? (0) 2023.12.20 동적바인딩과 @Override (0) 2023.12.20