brunch

You can make anything
by writing

C.S.Lewis

by 서준수 Mar 15. 2020

다트 컬렉션 (Dart Collection)

플러터를 위한 다트 프로그래밍

다트의 컬렉션

컬렉션은 다수의 데이터처리할 수 있는 자료구조이다. 하나의 데이터가 아닌 데이터의 집합이기 때문에 반복 가능하기도 하다. 반복 가능하다는 의미를 단순하게 생각하면 반복문 내에서 순회할 수도 있다는 것이다.


다트에서는 자체적으로 세 가지 컬렉션을 제공한다.


List : 데이터 순서가 있고 중복 허용

Set : 데이터 순서가 없고 중복 허용하지 않음

Map : 키(key)와 값(value)으로 구성되며 키는 중복되지 않고 값은 중복 가능


보통 컬렉션의 기본 중의 기본은 배열(array)이다. 그러나 다트에서는 List가 곧 배열이다.


1. List

List는 데이터를 여러 개 담을 수 있는 자료구조이다. 데이터를 List에 담을 때 순서를 가지기 때문에 배열을 대체할 수 있고 데이터에 순차적으로 접근하기 쉽다. 기본 형태는 다음과 같다.


List<데이터 타입> 변수명 = [데이터1, 데이터2, 데이터3, ...];

또는

List<데이터 타입> 변수명 = List();

colors .add(데이터1);

colors .add(데이터2);

colors .add(데이터3);


ex)

List<String> colors = ['Red', 'Orange', 'Yellow'];

또는

List<String> colors = List();

colors .add('Red');

colors .add('Orange');

colors .add('Yellow');


위 예제에서는 List에 들어갈 데이터 타입을 String으로 지정하였다. 그런데 만약에 List에 여러 타입의 데이터를 섞어서 넣고 싶으면 어떻게 해야 할까? 가능할까? 가능하다.


다트의 변수에서 배웠던 타입 추론 키워드인 dynamic이나 var를 사용하면 된다.

Line 2를 보면 list1의 타입은 List<dynamic>이다. 이것은 List에 들어가는 데이터 타입이 dynamic이라는 의미다. 이렇게 사용하면 dynamic은 미지정 타입이고 타입 변경도 가능하기 때문에 list의 데이터로 다양한 타입을 넣을 수 있다.


Line 3과 같이 list2의 타입을 dynamic으로 하면 list2의 데이터를 보고 list2의 타입을 추론할 것이다. 이때 추론되는 타입은 list1처럼 List<dynamic>이 될 것이다.


Line 4는 dynamic 타입인 경우에는 타입 변경이 가능하기 때문에 List<dynamic> 타입으로 추론되었을 list2에 정수 1을 할당하면 int형으로 다시 재지정될 것이다. 따라서 당연히 에러 없이 잘 실행된다.


Line 5와 같이 var 타입을 사용해도 무방하다. var 역시 dynamic과 같이 타입 미지정인 상태이고 list3에 할당된 List의 형태를 보면 타입을 List<dynamic>으로 추론하여 지정될 것이기 때문이다. 단 list3에 정수 1을 할당하려고 하면 타입 변경을 시도하는 것이기 때문에 에러가 발생한다.( var list3 = List<String>();과 같이 사용할 수도 있다.)


List의 각 데이터에 접근하려면 인덱스를 사용하면 된다. 예를 들어 list1의 첫 번째 요소(element)에 접근하려면 list1[0]이다. 인덱스는 0부터 시작한다. List는 순서가 있는 데이터의 집합이기 때문에 for문을 이용하면 순차적으로 데이터에 접근이 가능하다.


Line 8을 보면 for문을 이용하여 list1의 데이터를 출력하고 있다. 이때 인덱스의 범위를 i < list1.length로 지정했다. list1.length는 list1의 크기를 나타낸다. 크기는 list1에 포함된 요소의 수이다. 즉 list1의 length는 3이다.


리스트에서 사용되는 주요 메서드와 프로퍼티는 다음과 같다.


indexOf(요소) : 요소의 인덱스 값

add(데이터) : 데이터 추가

addAll([데이터1, 데이터2]) : 여러 데이터 추가

remove(요소) : 요소 삭제

removeAt(인덱스) : 지정한 인덱스의 요소 삭제하고 해당 요소 리턴

contains(요소) : 요소가 포함되었으면 true, 아니면 false

clear() : 리스트 요소 전체 삭제

sort() : 리스트 요소 정렬

first : 리스트 첫 번째 요소

last : 리스트 마지막 요소

reversed : 리스트 요소 역순

isNotEmpty : 리스트가 비어있지 않으면 true, 비었으면 false

isEmpty : 리스트가 비었으면 true, 비어있지 않으면 false

single : 리스트에 단 1개의 요소만 있다면 해당 요소 리턴


위 메서드와 프로퍼티를 사용한 예제는 다음과 같다.

코드가 길어져 외부 syntax highlighter 사용
실행결과

메서드와 프로퍼티의 역할과 위 예제를 하나씩 매칭 해보면 어떻게 동작하는지 알 수 있다.


2. Set

Set은 데이터를 여러 개 담을 수 있는 자료구조 것은 List와 동일하다. 하지만 데이터의 순서가 없고 중복된 요소를 허용하지 않는다. 기본 형태는 다음과 같다.


Set<데이터 타입> 변수명 = {데이터1, 데이터2, 데이터3, ...};

또는

Set<데이터 타입> 변수명 = Set();

colors .add(데이터1);

colors .add(데이터2);

colors .add(데이터3);


ex)

Set<String> colors = {'RED', 'Orange', 'Yellow'};

또는

Set<String> colors = Set();

colors .add('Red');

colors .add('Orange');

colors .add('Yellow');


Set은 List와 거의 유사한 형태이다. 주의할 점은 초깃값을 넣을 때 List는 [ ]를 사용했지만 Set은 { }를 사용한다. 또한 중복을 허용하지 않기 때문에 다음 예제와 같이 같은 값을 여러 번 추가해도 단 하나만 존재한다.

순서를 가지지 않기 각 요소에 때문에 인덱스로는 접근하지 못하지만 for..in문을 통해서 접근 가능하다. for..in문은 반복 시 in 뒤에 선언된 객체에서 하나의 요소를 가져와 in 앞에 선언된 변수에 할당한다.


Set의 메서드와 프로퍼티는 List와 겹치는 부분이 많지만 인덱스와 관련된 것은 사용하지 않는다. 이 또한 Set은 데이터 순서를 가지지 않기 때문이다. 따라서 다음의 메서드와 프로퍼티는 사용하지 못한다.


indexOf()

removeAt()

sort()

reversed



3. Map

Map은 키와 값으로 이뤄진 것이 가장 큰 특징이다. 키와 값은 한 쌍으로 이뤄진다. 키에 대한 값이 매칭 되어 있어서 빠른 탐색이 가능하다.


맵은 순서를 가지지 않지만 키를 정수로 설정하면 순서를 가진 것처럼 사용할 수도 있다. 키는 중복이 불가하고 값은 중복 가능하다. 만약 키 중복이 된다면 다음과 같은 상황에서 어떤 값을 가져와야 할까? 이런 상황이 문제가 되기 때문에 키에 대한 중복은 허용하지 않는다.

어디로 가야 하오?


기본 형태는 다음과 같다.


Map<키 타입, 값 타입> 변수명 = {
  키1:값1,
  키2:값2,
  키3:키3
};

또는

Map<키 타입, 값 타입> 변수명 = Map();

변수명[1] = 값1;

변수명[2] = 값2;

변수명[3] = 값3;


ex)

Map<int, String> testMap = {
  1:'Red',
  2:'Orange',
  3:'Yellow'
};

또는

Map<int, String> testMap = Map();
testMap[1] = 'Red';
testMap[2] = 'Orange';
testMap[3] = 'Yellow';


Map의 간단한 예제는 다음과 같다.

Line 7은 새로운 키인 4에 새로운 값 'Green'을 추가하는 것이다.

Line 10은 키 1의 값인 'Red'를 가져와서 출력하는 것이다.

Line 11처럼 존재하지 않는 키인 5의 값을 가져오려고 하면 null을 리턴한다.


map에서 키에 대한 값의 맵핑을 새로운 값으로 변경하려면 update()라는 메서드를 이용하면 된다.

Line 5는 키 1의 값을 'NewRed' 바꾸는 것이다. ifAbsent는 변경하고자 하는 키가 없을 때  해당 키와 값을 추가하도록 설정하는 것이다.

Line 6을 보면 키 5는 존재하지 않는다. 따라서 키 5가 추가되면서 값은 ifAbsent에서 지정한 'NewColor'가 된다.

이전 14화 다트 추상 클래스 (Abstract Class)
brunch book
$magazine.title

현재 글은 이 브런치북에
소속되어 있습니다.

작품 선택

키워드 선택 0 / 3 0

댓글여부

afliean
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari