본문 바로가기
flutter

플러터 - 컬렉션 타입 — List, Set, Map

by 들풀민들레 2023. 3. 13.
본 글은 [Do it! 깡샘의 플러터&다트 프로그래밍] 의 내용을 발췌한 것입니다.

 

 

책의 모든 내용을 저자 직강으로 진행한 강의는 ssamz.com 에서 들으실 수 있습니다.

 

컬렉션collection 타입이란 한 변수에 여러 데이터를 저장하는 방법으로 배열(Array), 리스트(List), 집합(Set), 맵(Map) 등이 있습니다. 배열과 리스트는 여러 데이터를 저장하고 저장된 순서를 나타내는 인덱스값으로 이용한다는 공통점이 있습니다. 따라서 다트에서는 둘을 구분하지 않으므로 배열이 리스트이고 리스트가 곧 배열이라고 보면 됩니다.


리스트 타입


List는 데이터를 여러 개 저장하고 인덱스값으로 데이터를 이용하는 컬렉션 타입의 클래스 입니다. 다음 코드에서는 list1이라는 이름으로 List 타입 변수를 선언했습니다. 리스트를 선언하면서 초기화할 때는 대괄호([])를 이용합니다. 다음 코드에서 list1 변수는 List 타입으로 선언했지만 리스트에 대입할 데이터의 타입을 지정하지 않았으므로 dynamic 타입 리스트가 됩니다. 따라서 모든 타입의 데이터를 저장할 수 있습니다.

 

main() {
	List list1 = [10, 'hello', true];
	list1[0] = 20;
	list1[1] = 'world';
	print('List : [${list1[0]}, ${list1[1]}, ${list1[2]}]');
}

특정한 타입의 데이터만 저장하는 리스트를 선언할 때는 다음처럼 해당 데이터 타입을 제네릭generic*으로 명시해 주면 됩니다. 다음 코드에서 list2는 List<int>로 선언해 int 타입만 대입할 수 있도록 했습니다. 따라서 list2에 int가 아닌 다른 타입의 데이터를 대입하면 오류가 발생합니다.

 

main() {
	List<int> list2 = [10, 20, 30];
	list2[0] = 'hello'; // 오류
}

리스트를 선언할 때 초기화한 데이터에서 더 추가하거나 제거하려면 add()나 removeAt() 함수를 이용합니다.

 

main() {
	List<int> list2 = [10, 20, 30];
	print(list2);
	list2.add(40);
	list2.add(50);
	print(list2);
	list2.removeAt(0);
	print(list2);
}

리스트를 선언할 때 데이터를 몇 개 저장할지 크기를 지정할 수 있습니다. 이때에는 filled(), generate()라는 함수를 사용합니다. filled(), generate()는 List 클래스에 선언된 생성자입니다. 생성자란 객체를 만들 때 자동으로 실행되는 함수입니다. 06장에서 객체지향 프로그래밍 기법을 다룰때 자세히 살펴보겠습니다. 여기서는 생성자를 호출하면 객체가 생성된다고 생각하면 됩니다.
오른쪽 코드에서 list3은 List<int>.filled(3, 0)으로 선언했습니다. filled() 생성자의 첫 번째 매개변수는 리스트의 크기입니다. 3이라고 지정했으므로 데이터 3개를 저장할 수 있는 List 객체가 생성됩니다. 그리고 두 번째 매개변수는 리스트의 초깃값입니다. 0으로 지정했으므로 데이터 3개가 모두 0으로 초기화됩니다.

 

main() {
	var list3 = List<int>.filled(3, 0);
	print(list3); // [0, 0, 0]
	list3[0] = 10;
	list3[1] = 20;
	list3[2] = 30;
	print(list3); // [10, 20, 30]
	list3.add(40); // 런 타임 오류
}

그런데 list3은 크기가 3이므로 4번째 데이터를 추가한 list3.add(40) 코드는 런 타임 때 오류가 발생합니다. 리스트를 선언할 때 크기를 지정하면 그 크기만큼만 데이터를 추가할 수 있습니다. 만약 처음에 지정한 크기보다 많은 데이터를 저장할 수 있도록 허용하려면 filled() 생성자에 growable 매개변수를 true로 지정해 주어야 합니다.

 

main() {
	var list3 = List<int>.filled(3, 0, growable: true);
	print(list3);
	list3[0] = 10;
	list3[1] = 20;
	list3[2] = 30;
	print(list3);
	list3.add(40);
	print(list3);
}

리스트를 초기화할 때 특정한 로직으로 구성된 데이터를 지정할 수도 있습니다. 이때는 초깃값을 지정하는 두 번째 매개변수를 함수로 지정하면 되는데, generate() 생성자가 이러한 기능을 제공합니다. 다음 코드에서는 generate() 생성자의 두 번째 매개변수를 (index) => index * 10로 지정했는데 이는 다트에서 함수를 선언하는 기법이며 이후 함수를 다루는 부분에서 자세히 설명하겠습니다.

 

main() {
	var list4 = List<int>.generate(3, (index) => index * 10, growable: true);
	print(list4);
}

집합 타입


Set은 List와 마찬가지로 여러 건의 데이터를 저장하는 컬렉션 타입의 클래스이며 인덱스값으로 데이터에 접근합니다. 리스트와 차이가 있다면 중복 데이터를 허용하지 않습니다. 집합 타입 변수를 선언하면서 초기화할 때는 중괄호({})를 이용합니다.

 

main() {
	Set<int> set1 = {10, 20, 10};
	print(set1);
	set1.add(30);
	set1.add(40);
	print(set1);
	Set<int> set2 = Set();
	set2.add(10);
	set2.add(20);
	print(set2);
}

맵 타입


Map은 여러 건의 데이터를 키와 값 형태로 저장하는 타입입니다. 맵에 저장되는 데이터는 항상 키를 가져야 하며 저장된 데이터에 접근할 때는 인덱스가 아닌 키를 이용합니다.

 

main() {
	Map<String, String> map1 = {'one':'hello', 'two':'world'};
	print(map1['one']);
	map1['one'] = 'world';
	print(map1['one']);
}

 

 

 

 

책의 모든 내용을 저자 직강으로 진행한 강의는 ssamz.com 에서 들으실 수 있습니다.