List 는 칸이 모자라면 알아서 늘린다
Esc

    List 는 칸이 모자라면 알아서 늘린다

    –C#자료구조

    배열은 만들 때 칸 개수가 정해지고 그 뒤로 안 바뀝니다. 개수를 미리 아는 것은 괜찮습니다. 문제는 모를 때입니다.

    사용자가 입력하는 대로 담아야 한다면 몇 칸을 잡아야 할까요. 앞에서 본 방식대로 넉넉하게 잡을 수는 있습니다.

    int[] nums = new int[1000];
    int count = 0;                  // 지금 몇 개 들어 있는지 따로 세야 합니다

    칸 1000개를 잡아 두고 3개만 쓰면 997칸이 놀고, 1001개가 들어오면 터집니다. 그리고 몇 개가 들어 있는지를 변수로 따로 관리해야 합니다. nums.Length 는 1000이지 3이 아니니까요.

    칸이 모자라면 알아서 늘리고, 개수도 스스로 세는 것이 List 입니다.

    List 는 이렇게 생겼다

    using System.Collections.Generic;
    
    List<int> nums = new List<int>();
    
    nums.Add(90);
    nums.Add(85);
    nums.Add(78);
    
    Console.WriteLine(nums.Count);     // 3
    Console.WriteLine(nums[1]);        // 85

    List<int> 의 꺾쇠 안이 담을 타입입니다. List<string>, List<double> 처럼 바꿔 쓰면 됩니다. 이 꺾쇠 문법의 정체는 나중에 제네릭에서 다룹니다. 지금은 “담을 타입을 적는 자리” 정도로 보면 충분합니다.

    배열과 다른 점이 두 가지 보입니다.

    • 만들 때 칸 개수를 안 적습니다.
    • 개수가 Length 가 아니라 Count 입니다. 그리고 실제로 들어 있는 개수입니다.

    꺼내는 것은 배열과 똑같이 대괄호에 번호입니다. 인덱스도 0부터입니다.

    하는 일 배열 List
    만들기 new int[3] new List<int>()
    개수 Length (칸 수) Count (들어 있는 수)
    꺼내기 a[0] list[0]
    넣기 a[0] = 5 list.Add(5)
    빼기 없음 list.RemoveAt(0)

    속은 그냥 배열이다

    List 가 마법을 부리는 것은 아닙니다. 안에 배열을 하나 들고 있습니다.

    칸이 꽉 찼는데 하나를 더 넣으라고 하면, 앞 글 마지막에서 우리가 손으로 했던 일을 그대로 합니다. 더 큰 배열을 새로 만들고, 전부 옮겨 담고, 새 배열을 쓰기 시작합니다.

    늘릴 때 두 배로 잡는 것이 요령입니다. 한 칸씩만 늘리면 Add 할 때마다 전부 옮겨야 해서 앞에서 본 문자열 + 와 같은 꼴이 납니다. 두 배로 잡으면 옮기는 일이 점점 드물게 일어나서, 평균으로 보면 Add 하나가 거의 공짜에 가까워집니다.

    몇 개쯤 들어올지 짐작이 되면 미리 알려줄 수도 있습니다.

    List<int> nums = new List<int>(1000);   // 처음부터 1000칸 잡고 시작

    이건 칸 개수를 정하는 게 아니라 처음에 잡을 크기를 알려주는 것입니다. 1001개를 넣어도 터지지 않고 알아서 늘어납니다. 옮기는 일을 줄여 줄 뿐입니다.

    중간에 넣고 빼면 밀린다

    List 는 중간에 끼워 넣거나 빼는 것도 됩니다.

    nums.Insert(0, 100);     // 맨 앞에 끼워 넣기
    nums.RemoveAt(0);        // 첫 칸 빼기

    편해 보이는데 공짜가 아닙니다. 배열은 칸이 빈틈없이 붙어 있어야 하니까, 맨 앞에 하나 끼워 넣으면 뒤의 모든 값이 한 칸씩 밀려야 합니다. 빼면 반대로 한 칸씩 당겨집니다.

    들어 있는 개수만큼 움직입니다. 위 그림에서 옮긴 칸 수를 보세요. 맨 뒤는 0이고 맨 앞은 들어 있는 만큼입니다.

    하는 일 비용
    list[i] 로 꺼내기 어디를 꺼내든 같다
    맨 뒤에 Add 대부분 그냥 한 칸 채운다
    중간이나 앞에 Insert / RemoveAt 뒤에 있는 것들이 전부 밀린다

    만 개짜리 리스트의 맨 앞을 반복문 안에서 계속 지우고 있다면, 그건 겉보기와 달리 무거운 코드입니다.

    배열이냐 List 냐

    개수가 변하면 List, 고정이면 배열입니다.

    요일 7개, 바둑판 19 × 19 처럼 개수가 처음부터 정해진 것은 배열이 맞습니다. 개수가 코드에 적혀 있으니 읽는 사람도 “여기는 안 늘어난다” 를 압니다.

    인벤토리, 접속한 사용자 목록처럼 실행 중에 개수가 변하는 것은 List 입니다. 배열로 하면 결국 List 가 해 주는 일을 손으로 다시 만들게 됩니다.

    애매하면 List 를 쓰면 됩니다. 실무에서 훨씬 자주 씁니다.

    정리

    • List 는 칸이 모자라면 알아서 늘어나고, 들어 있는 개수를 Count 로 알려줍니다.
    • 꺾쇠 안이 담을 타입입니다. 꺼내는 것은 배열과 똑같이 대괄호에 번호입니다.
    • 속은 배열입니다. 꽉 차면 두 배 크기로 새로 만들어 전부 옮깁니다.
    • 두 배로 늘리기 때문에 옮기는 일이 드물게 일어납니다. Add 는 대체로 싸게 끝납니다.
    • 중간이나 앞에 넣고 빼면 뒤가 전부 밀립니다. 이건 싼 연산이 아닙니다.
    • 개수가 변하면 List, 고정이면 배열입니다.