ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 너무 다양한 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

     

    1. 배열
    • 자바에서 배열과 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
Designed by Tistory.