πŸ“š

Dart Collections

List, Set, Map + spread, collection for/if

Dart provides 3 core collections: List (ordered, duplicates OK), Set (unique, set operations), and Map (key-value pairs). Spread operator (...) merges collections, collection for/if creates dynamic elements within literals, and method chaining with map/where/fold builds powerful data transformation pipelines.

1. List β€” μˆœμ„œ μžˆλŠ” μ»¬λ ‰μ…˜

ListλŠ” μˆœμ„œκ°€ 있고 쀑볡을 ν—ˆμš©ν•˜λŠ” κ°€μž₯ 기본적인 μ»¬λ ‰μ…˜μž…λ‹ˆλ‹€. 인덱슀둜 μš”μ†Œμ— μ ‘κ·Όν•˜λ©°, λ‹€μ–‘ν•œ 생성 방식을 μ œκ³΅ν•©λ‹ˆλ‹€.

List 생성

var fruits = ['사과', 'λ°”λ‚˜λ‚˜', 'μ˜€λ Œμ§€'];\nList<String> names = ['홍길동', 'κΉ€μ² μˆ˜', '이영희'];\nvar emptyList = <int>[];\nvar fixedList = List<int>.filled(5, 0); // [0, 0, 0, 0, 0]\nvar generatedList = List<int>.generate(5, (i) => i * i); // [0, 1, 4, 9, 16]

List μ ‘κ·Ό & μ‘°μž‘

var fruits = ['사과', 'λ°”λ‚˜λ‚˜', 'μ˜€λ Œμ§€', 'λ”ΈκΈ°', '포도'];\nprint(fruits[0]); // 사과\nprint(fruits.length); // 5\nprint(fruits.first); // 사과\n\nfruits.add('ν‚€μœ„');\nfruits.addAll(['멜둠', 'μˆ˜λ°•']);\nfruits.remove('λ°”λ‚˜λ‚˜');\nfruits.removeAt(1);\nfruits.removeWhere((fruit) => fruit.length <= 2);\nfruits.sort();\nprint(fruits.indexOf('포도'));\nprint(fruits.contains('사과')); // true

List λ³€ν™˜ (map, where, fold, expand)

var numbers = [1, 2, 3, 4, 5];\nvar doubled = numbers.map((n) => n * 2).toList(); // [2, 4, 6, 8, 10]\nvar evenNumbers = numbers.where((n) => n.isEven).toList(); // [2, 4]\nvar sum = numbers.fold<int>(0, (prev, curr) => prev + curr); // 15\nvar product = numbers.reduce((a, b) => a * b); // 120\n\nvar nested = [[1, 2], [3, 4], [5]];\nvar flattened = nested.expand((list) => list).toList(); // [1, 2, 3, 4, 5]

List μŠ¬λΌμ΄μ‹±

var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\nvar slice = numbers.sublist(2, 5); // [3, 4, 5]\nvar copy = List<int>.from(numbers);\nnumbers.replaceRange(0, 3, [99, 98, 97]);\nvar reversed = numbers.reversed.toList();\nnumbers.fillRange(5, 8, 0);

2. Set β€” 쀑볡 μ—†λŠ” μ»¬λ ‰μ…˜

Set은 쀑볡을 ν—ˆμš©ν•˜μ§€ μ•ŠλŠ” μ»¬λ ‰μ…˜μœΌλ‘œ, μˆ˜ν•™μ˜ μ§‘ν•© μ—°μ‚°(ν•©μ§‘ν•©, ꡐ집합, μ°¨μ§‘ν•©)을 μ§€μ›ν•©λ‹ˆλ‹€.

Set 생성

var fruits = {'사과', 'λ°”λ‚˜λ‚˜', 'μ˜€λ Œμ§€'};\nSet<String> names = {'홍길동', 'κΉ€μ² μˆ˜', '이영희'};\nvar emptySet = <int>{};\nvar numbers = Set<int>.from([1, 2, 2, 3, 3, 3, 4, 5, 5]); // {1, 2, 3, 4, 5}

Set μ§‘ν•© μ—°μ‚°

var set1 = {1, 2, 3, 4, 5};\nvar set2 = {4, 5, 6, 7, 8};\n\nvar union = set1.union(set2); // {1, 2, 3, 4, 5, 6, 7, 8}\nvar intersection = set1.intersection(set2); // {4, 5}\nvar difference = set1.difference(set2); // {1, 2, 3}\n\nset1.add(6);\nset1.addAll({7, 8, 9});\nset1.remove(9);\nprint(set1.contains(5)); // true\nprint({1, 2}.isSubsetOf(set1)); // true

Set λ³€ν™˜

var numbers = {1, 2, 3, 4, 5};\nvar doubled = numbers.map((n) => n * 2).toSet();\nvar evenNumbers = numbers.where((n) => n.isEven).toSet();\nvar numbersList = numbers.toList();

3. Map β€” ν‚€-κ°’ 쌍 μ»¬λ ‰μ…˜

Map은 ν‚€-κ°’ 쌍으둜 데이터λ₯Ό μ €μž₯ν•©λ‹ˆλ‹€. ν‚€λ‘œ λΉ λ₯΄κ²Œ 값을 검색할 수 μžˆμŠ΅λ‹ˆλ‹€.

Map 생성

var person = {\n 'name': '홍길동',\n 'age': 30,\n 'isStudent': false\n};\nMap<String, int> scores = {\n 'μˆ˜ν•™': 90,\n 'μ˜μ–΄': 85,\n 'κ³Όν•™': 95\n};\nvar emptyMap = <String, dynamic>{};\nvar map2 = Map.from({'a': 1, 'b': 2});\nvar map3 = Map.of({'x': 10, 'y': 20});

Map μ ‘κ·Ό & μ‘°μž‘

print(person['name']); // 홍길동\nprint(person.containsKey('age')); // true\nprint(person.containsValue(30)); // true\nprint(person.keys.toList());\nprint(person.values.toList());\n\nperson['email'] = 'hong@example.com';\nperson['age'] = 31;\nperson.remove('isStudent');\nperson.addAll({'address': 'μ„œμšΈμ‹œ', 'phone': '010-1234-5678'});\nperson.putIfAbsent('gender', () => '남성');

Map λ³€ν™˜

var scores = {'μˆ˜ν•™': 90, 'μ˜μ–΄': 85, 'κ³Όν•™': 95, 'κ΅­μ–΄': 80};\n\n// map으둜 ν‚€-κ°’ λ³€ν™˜\nvar scaledScores = scores.map((k, v) => MapEntry(k, v * 1.1));\n\n// entries.where둜 필터링\nvar highScores = scores.entries\n .where((entry) => entry.value >= 90);\n\n// forEach둜 순회\nscores.forEach((key, value) {\n print('$key: $value');\n});

4. 반볡문 (Loops)

DartλŠ” for, for-in, while, do-while, forEach λ“± λ‹€μ–‘ν•œ 반볡 방식을 μ œκ³΅ν•©λ‹ˆλ‹€.

// κΈ°λ³Έ for 루프\nfor (int i = 0; i < 5; i++) {\n print(i);\n}\n\n// for-in 루프\nvar fruits = ['사과', 'λ°”λ‚˜λ‚˜', 'μ˜€λ Œμ§€'];\nfor (var fruit in fruits) {\n print(fruit);\n}\n\n// while 루프\nint count = 0;\nwhile (count < 5) {\n print(count);\n count++;\n}\n\n// forEach λ©”μ„œλ“œ\nvar numbers = [1, 2, 3, 4, 5];\nnumbers.forEach((number) {\n print(number * 2);\n});\n\n// Map forEach\nvar scores = {'μˆ˜ν•™': 90, 'μ˜μ–΄': 85, 'κ³Όν•™': 95};\nscores.forEach((subject, score) {\n print('$subject: $score점');\n});

루프 μ œμ–΄ (break, continue, λ ˆμ΄λΈ”)

// break β€” 루프 μ¦‰μ‹œ μ’…λ£Œ\nfor (int i = 0; i < 10; i++) {\n if (i == 5) break;\n print(i); // 0, 1, 2, 3, 4\n}\n\n// continue β€” ν˜„μž¬ 반볡 κ±΄λ„ˆλ›°κΈ°\nfor (int i = 0; i < 5; i++) {\n if (i == 2) continue;\n print(i); // 0, 1, 3, 4\n}\n\n// λ ˆμ΄λΈ”λ‘œ 쀑첩 루프 μ œμ–΄\nouterLoop: for (int i = 0; i < 3; i++) {\n for (int j = 0; j < 3; j++) {\n if (i == 1 && j == 1) {\n break outerLoop;\n }\n print('$i, $j');\n }\n}

5. μŠ€ν”„λ ˆλ“œ μ—°μ‚°μž (...)

μŠ€ν”„λ ˆλ“œ μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•˜λ©΄ μ»¬λ ‰μ…˜μ˜ λͺ¨λ“  μš”μ†Œλ₯Ό λ‹€λ₯Έ μ»¬λ ‰μ…˜ μ•ˆμ— 펼칠 수 μžˆμŠ΅λ‹ˆλ‹€. null-aware μŠ€ν”„λ ˆλ“œ(...?)도 μ§€μ›ν•©λ‹ˆλ‹€.

var list1 = [1, 2, 3];\nvar list2 = [0, ...list1, 4, 5]; // [0, 1, 2, 3, 4, 5]\n\n// null-aware μŠ€ν”„λ ˆλ“œ\nList<int>? nullableList;\nvar combined = [0, ...?nullableList, 1]; // [0, 1]\n\n// Map μŠ€ν”„λ ˆλ“œ\nvar map1 = {'a': 1, 'b': 2};\nvar map2 = {'c': 3, ...map1}; // {'c': 3, 'a': 1, 'b': 2}\n\n// Set μŠ€ν”„λ ˆλ“œ\nvar set1 = {1, 2, 3};\nvar set2 = {0, ...set1, 4}; // {0, 1, 2, 3, 4}

6. μ»¬λ ‰μ…˜ for / if

μ»¬λ ‰μ…˜ λ¦¬ν„°λŸ΄ μ•ˆμ—μ„œ for와 ifλ₯Ό μ‚¬μš©ν•˜μ—¬ λ™μ μœΌλ‘œ μš”μ†Œλ₯Ό 생성할 수 μžˆμŠ΅λ‹ˆλ‹€.

// μ»¬λ ‰μ…˜ for\nvar numbers = [1, 2, 3];\nvar doubled = [\n 0,\n for (var n in numbers) n * 2,\n 4\n]; // [0, 2, 4, 6, 4]\n\n// μ»¬λ ‰μ…˜ if\nbool includeZ = true;\nvar letters = ['a', 'b', if (includeZ) 'z']; // ['a', 'b', 'z']\n\n// μ‹€μ „ ν™œμš© β€” 쑰건뢀 UI 리슀트 ꡬ성\nvar items = [\n 'home',\n if (userLoggedIn) 'profile',\n for (var item in defaultItems) item,\n if (isAdmin) 'admin'\n];

7. μ œλ„ˆλ ˆμ΄ν„° (sync* / async*)

μ œλ„ˆλ ˆμ΄ν„° ν•¨μˆ˜λŠ” yieldλ₯Ό μ‚¬μš©ν•˜μ—¬ 값을 ν•˜λ‚˜μ”© μƒμ„±ν•©λ‹ˆλ‹€. 동기 μ œλ„ˆλ ˆμ΄ν„°(sync*)λŠ” Iterable을, 비동기 μ œλ„ˆλ ˆμ΄ν„°(async*)λŠ” Stream을 λ°˜ν™˜ν•©λ‹ˆλ‹€.

동기 μ œλ„ˆλ ˆμ΄ν„° (sync*)

Iterable<int> getNumbers(int n) sync* {\n for (int i = 0; i < n; i++) {\n yield i;\n }\n}\n\nvoid main() {\n for (var num in getNumbers(5)) {\n print(num); // 0, 1, 2, 3, 4\n }\n}

비동기 μ œλ„ˆλ ˆμ΄ν„° (async*)

Stream<int> countStream(int n) async* {\n for (int i = 1; i <= n; i++) {\n await Future.delayed(Duration(seconds: 1));\n yield i;\n }\n}\n\nvoid main() async {\n await for (var num in countStream(5)) {\n print(num); // 1μ΄ˆλ§ˆλ‹€ 1, 2, 3, 4, 5\n }\n}

8. κ³ κΈ‰ λ³€ν™˜ & λ©”μ„œλ“œ 체이닝

μ—¬λŸ¬ λ©”μ„œλ“œλ₯Ό μ²΄μ΄λ‹ν•˜μ—¬ 데이터 λ³€ν™˜ νŒŒμ΄ν”„λΌμΈμ„ ꡬ성할 수 μžˆμŠ΅λ‹ˆλ‹€.

var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\n\nvar result = numbers\n .where((n) => n % 2 == 0) // 짝수 ν•„ν„°\n .map((n) => n * n) // 제곱\n .takeWhile((n) => n <= 36) // 36 μ΄ν•˜λ§Œ\n .fold(0, (sum, n) => sum + n); // 합계\n\n// κ·Έλ£Ήν•‘\nvar fruits = ['사과', 'λ°”λ‚˜λ‚˜', '체리', '블루베리', '아보카도'];\nvar byFirstLetter = fruits.fold<Map<String, List<String>>>({}, (map, fruit) {\n var firstLetter = fruit[0];\n map[firstLetter] = (map[firstLetter] ?? [])..add(fruit);\n return map;\n});

9. μΊμŠ€μΌ€μ΄λ“œ ν‘œκΈ°λ²• (..)

μΊμŠ€μΌ€μ΄λ“œ μ—°μ‚°μž(..)λ₯Ό μ‚¬μš©ν•˜λ©΄ 동일 객체에 μ—°μ†μœΌλ‘œ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•  수 μžˆμŠ΅λ‹ˆλ‹€.

var list = [1, 2, 3]\n ..add(4)\n ..addAll([5, 6])\n ..remove(2)\n ..sort();\n\nvar map = {'user': {'name': '홍길동', 'age': 30}}\n ..['user']['email'] = 'hong@example.com'\n ..['user']['age'] = 31\n ..['active'] = true;

10. Null-Aware μ»¬λ ‰μ…˜ μ‘°μž‘

nullable μ»¬λ ‰μ…˜μ„ μ•ˆμ „ν•˜κ²Œ λ‹€λ£¨λŠ” νŒ¨ν„΄μž…λ‹ˆλ‹€.

List<String>? nullableList;\nnullableList?.add('ν•­λͺ©'); // null이면 λ¬΄μ‹œ\nvar list = nullableList ?? []; // null이면 빈 리슀트\nlist.add('ν•­λͺ©');\n\nMap<String, int>? scoresMap;\nscoresMap ??= {}; // null이면 빈 λ§΅ ν• λ‹Ή\nscoresMap['μˆ˜ν•™'] = 90;

11. μ‹€μ „ 예제 β€” 학생 데이터 νŒŒμ΄ν”„λΌμΈ

μ‹€μ „μ—μ„œ 자주 μ‚¬μš©ν•˜λŠ” μ»¬λ ‰μ…˜ ν™œμš© νŒ¨ν„΄μž…λ‹ˆλ‹€. 객체 리슀트λ₯Ό map/fold둜 λ³€ν™˜ν•˜μ—¬ μ§‘κ³„ν•©λ‹ˆλ‹€.

class Student {\n final String name;\n final int age;\n final Map<String, int> scores;\n Student(this.name, this.age, this.scores);\n}\n\nvoid main() {\n final students = [\n Student('홍길동', 20, {'μˆ˜ν•™': 90, 'μ˜μ–΄': 85, 'κ³Όν•™': 95}),\n Student('κΉ€μ² μˆ˜', 22, {'μˆ˜ν•™': 75, 'μ˜μ–΄': 90, 'κ³Όν•™': 85}),\n Student('이영희', 21, {'μˆ˜ν•™': 85, 'μ˜μ–΄': 92, 'κ³Όν•™': 88}),\n Student('λ°•λ―Όμˆ˜', 23, {'μˆ˜ν•™': 95, 'μ˜μ–΄': 80, 'κ³Όν•™': 92}),\n ];\n\n final averageScores = students.map((student) {\n final total = student.scores.values\n .fold<int>(0, (sum, score) => sum + score);\n final average = total / student.scores.length;\n return {'name': student.name, 'average': average};\n }).toList();\n}

μ»¬λ ‰μ…˜ 비ꡐ μš”μ•½

μ»¬λ ‰μ…˜μˆœμ„œμ€‘λ³΅μ ‘κ·Ό λ°©μ‹μ£Όμš” μš©λ„
ListOO인덱슀 [i]μˆœμ„œ μžˆλŠ” 데이터, λ°°μ—΄
SetXXcontains()쀑볡 제거, μ§‘ν•© μ—°μ‚°
MapXν‚€ X / κ°’ Oν‚€ [key]ν‚€-κ°’ λ§€ν•‘, JSON

핡심 정리

  • List β€” κ°€μž₯ λ²”μš©μ . map/where/fold둜 ν•¨μˆ˜ν˜• νŒŒμ΄ν”„λΌμΈ ꡬ성
  • Set β€” 쀑볡 μ œκ±°κ°€ ν•„μš”ν•  λ•Œ. union/intersection/difference둜 μ§‘ν•© μ—°μ‚°
  • Map β€” ν‚€λ‘œ λΉ λ₯Έ 검색. putIfAbsent/entries.where둜 쑰건뢀 μ‘°μž‘
  • μŠ€ν”„λ ˆλ“œ & μ»¬λ ‰μ…˜ for/if β€” λ¦¬ν„°λŸ΄ μ•ˆμ—μ„œ 동적 μ»¬λ ‰μ…˜ 생성
  • μ œλ„ˆλ ˆμ΄ν„° β€” sync*(Iterable) / async*(Stream)둜 값을 μ§€μ—° 생성

Implementation Steps

1

List β€” add/addAll to insert, map/where/fold for transform/filter/aggregate, method chaining for pipelines

2

Set β€” union/intersection/difference for set operations, useful for deduplication

3

Map β€” putIfAbsent (add only if key missing), entries.where for filtering, map() for key-value transform

4

Spread & collection for/if β€” [...list1, ...list2] merge, [for (var x in items) x.name], [if (flag) item]

Pros

  • Functional-style data pipelines with method chaining
  • Dynamic list creation within literals using spread/collection forΒ·if

Cons

  • Long chaining reduces readability

Use Cases

Converting API response JSON arrays to model lists Data processing: search filters, sorting, grouping