러스트의 표준 라이브러리에는 컬렉션
이라 불리는 여러 개의 매우 유용한 데이터 구조들이 포함되어 있습니다.
대부분의 다른 데이터 타입들은 하나의 특정한 값을 나타내지만, 컬렉션은 다수의 값을 담을 수 있습니다.
내장된 배열(build-in array)와 튜플 타입과는 달리, 이 컬렉션들이 가리키고 있는 데이터들은 힙에 저장되는데, 이는 즉 데이터량이 컴파일 타임에 결정되지 않아도 되며 프로그램이 실행될 때 늘어나거나 줄어들 수 있다는 의미입니다.
각각의 컬렉션 종류는 서로 다른 용량과 비용을 가지고 있으며, 여러분의 현재 상황에 따라 적절한 컬렉션을 선택하는 것은 시간이 지남에 따라 발전시켜야 할 기술입니다.
이번 장에서는 러스트 프로그램에서 굉장히 자주 사용되는 세 가지 컬렉션에 대해 논의해 보겠습니다:
- 벡터(vector) 는 여러 개의 값을 서로 붙어 있게 저장할 수 있도록 해줍니다.
- 스트링(string) 은 문자(character)의 모음입니다.
String
타입은 이전에 다루었지만, 이번 장에서는 더 깊이 있게 이야기해 보겠습니다. - 해쉬맵(hash map 은 어떤 값을 특정한 키와 연관지어 주도록 해줍니다. 이는 맵(map) 이라 일컫는 좀더 일반적인 데이터 구조의 특정한 구현 형태입니다.
표준 라이브러리가 제공해주는 다른 종류의 컬렉션에 대해 알고 싶으시면, the documentation를 봐 주세요.
벡터
우리가 보게될 첫번째 콜렉션은 벡터
라고도 알려진 Vec<T>
입니다.
- 벡터는 메모리 상에 서로 이웃하도록 모든 값을 집어넣는 단일 데이터 구조 안에 하나 이상의 값을 저장하도록 해줍니다.
- 벡터는 같은 타입의 값만을 저장할 수 있습니다.
새 벡터 만들기
비어있는 새 벡터를 만들기 위해서는, 아래의 Listing 8-1과 같이 Vec::new
함수를 호출해 줍니다:
let v: Vec<i32> = Vec::new();
- 여기에 타입 명시(type annotation)를 추가한 것을 주목하세요.
- 이 벡터에 어떠한 값도 집어넣지 않았기 때문에, 러스트는 우리가 저장하고자 하는 요소의 종류가 어떤 것인지 알지 못합니다.
- 벡터는 제네릭(generic)을 이용하여 구현되었습니다;
- 표준 라이브러리가 제공하는
Vec
타입은 어떠한 종류의 값이라도 저장할 수 있다는 것, - 그리고 특정한 벡터는 특정한 타입의 값을 저장할 때, 이 타입은 꺾쇠 괄호
(<>)
안에 적는다는 것만 알아두세요.
- 표준 라이브러리가 제공하는
- 일단 우리가 값을 집어넣으면 러스트는 우리가 저장하고자 하는 값의 타입을 대부분 유추할 수 있으므로, 좀 더 현실적인 코드에서는 이러한 타입 명시를 할 필요가 거의 없습니다.
- 초기값들을 갖고 있는
Vec<T>
을 생성하는 것이 더 일반적이며, 러스트는 편의를 위해vec!
매크로를 제공합니다. - 이 매크로는 우리가 준 값들을 저장하고 있는 새로운
Vec
을 생성합니다. 1
,2
,3
을 저장하고 있는 새로운Vec<i32>
을 생성할 것입니다:
let v = vec![1, 2, 3];
Listing 8-2: 값을 저장하고 있는 새로운 벡터 생성하기
초기 i32
값들을 제공했기 때문에, 러스트는 v
가 Vec
타입이라는 것을 유추할 수 있으며, 그래서 타입 명시는 필요치 않습니다.
벡터 갱신하기
벡터를 만들고 여기에 요소들을 추가하기 위해서 push
메소드를 사용할 수 있습니다:
let mut v = Vec::new();
v.push(5);
v.push(6);
v.push(7);
v.push(8);
Listing 8-3: push
메소드를 사용하여 벡터에 값을 추가하기
어떤 변수에 대해 그 변수가 담고 있는 값이 변경될 수 있도록 하려면, mut
키워드를 사용하여 해당 변수를 가변으로 만들어 줄 필요가 있습니다.
우리가 집어넣는 숫자는 모두 i32
타입이며, 러스트는 데이터로부터 이 타입을 추론하므로, 우리는 Vec<i32>
명시를 붙일 필요가 없습니다.