Dart-Sammlungstypen
Eine Sammlung ist eine Datenstruktur, die zum Speichern mehrerer Datenelemente verwendet wird.
Dart hat drei integrierte Kern-Sammlungstypen: List, Set und Map. In diesem Kapitel wird ihre Verwendung nacheinander vorgestellt.
List: Geordnete Liste
List ist der am häufigsten verwendete Sammlungstyp, der verwendet wird, um eine geordnete Gruppe von Elementen zu speichern, wobei Duplikate erlaubt sind.
Sie können auf jedes Element in einer List über seinen Index zugreifen (beginnend bei 0).
List erstellen
Beispiel
// Eine List mit Literalen erstellen
List<String> sites = ['EXAMPLE', 'Google', 'GitHub'];
print(Website-Liste: $sites);
// Typinferenz (generische Typen ausgelassen)
var numbers = [1, 2, 3, 4, 5];
print(Zahlenliste: $numbers);
// Eine leere Liste erstellen
var emptyList = <String>[];
// Eine Liste fester Länge mit List.filled erstellen
var zeros = List.filled(3, 0); // [0, 0, 0]
print(Gefüllte Liste: $zeros);
// Eine Liste mit List.generate erstellen
var squares = List.generate(5, (i) => i * i);
print(Liste der Quadratzahlen: $squares);
}
网站列表: [EXAMPLE, Google, GitHub] 数字列表: [1, 2, 3, 4, 5] 填充列表: [0, 0, 0] 平方数列表: [0, 1, 4, 9, 16]
Zugriff auf und Ändern von Listenelementen
Beispiel
var fruits = [Apfel, Banane, Orange];
// Zugriff über Index (beginnend bei 0)
print('Erste Frucht: ${fruits[0]}'); // Apfel
print('Letzte: ${fruits[fruits.length - 1]}'); // Orange
// Element ändern
fruits[1] = 'Traube';
print('Nach der Änderung: $fruits'); // [Apfel, Traube, Orange]
// Länge abrufen
print('Anzahl der Früchte: ${fruits.length}');
// Prüfen, ob leer
print('Ist die Liste leer? ${fruits.isEmpty}');
print('Ist die Liste nicht leer? ${fruits.isNotEmpty}');
}
第一个水果: 苹果 最后一个: 橙子 修改后: [苹果, 葡萄, 橙子] 水果数量: 3 列表为空? false 列表非空? true
Gängige Listenoperationen
Beispiel
var list = ['EXAMPLE', 'Dart'];
// Elemente hinzufügen
list.add('Flutter'); // Einzelnes Element hinzufügen
list.addAll(['Google', 'AI']); // Mehrere Elemente hinzufügen
print('Nach dem Hinzufügen: $list');
// Element an bestimmter Position einfügen
list.insert(1, 'Tutorial');
print('Nach dem Einfügen: $list');
// Elemente löschen
list.remove('AI'); // Nach Wert löschen
list.removeAt(0); // Nach Index löschen
list.removeLast(); // Letztes löschen
print('Nach dem Löschen: $list');
// Element finden
bool hasDart = list.contains('Dart');
int index = list.indexOf('Dart');
print('Enthält Dart? $hasDart, Position: $index');
// Sortieren
var nums = [3, 1, 4, 1, 5, 9];
nums.sort();
print('Nach dem Sortieren: $nums');
// Umkehren
var reversed = nums.reversed.toList();
print('Nach Umkehrung: $reversed');
// Unterliste abrufen
var subList = nums.sublist(0, 3);
print('Erste 3: $subList');
}
添加后: [EXAMPLE, Dart, Flutter, Google, AI] 插入后: [EXAMPLE, 教程, Dart, Flutter, Google, AI] After deletion: [教程, Dart, Flutter] 包含 Dart? true, 位置: 1 排序后: [1, 1, 3, 4, 5, 9] 反转后: [9, 5, 4, 3, 1, 1] 前3个: [1, 1, 3]
Funktionale Methoden auf List
Darts List unterstützt funktionale Methoden wie map, where und reduce, wodurch die Datenverarbeitung prägnanter wird.
Beispiel
var scores = [55, 78, 92, 60, 45, 88];
// where: Filter (Elemente beibehalten, die die Bedingung erfüllen)
var passed = scores.where((s) => s >= 60);
print('Bestandene Punktzahl: $passed');
// map: Abbildung (jedes Element in einen neuen Wert umwandeln)
var grades = scores.map((s) => s >= 60 ? 'Bestanden' : 'Nicht bestanden');
print('Note: $grades');
// Verketteter Aufruf von where + map
var highScores = scores
.wobei((s) => s >= 80)
.map((s) => 'Highscore: $s')
.toList();
print('Highscore-Liste: $highScores');
// reduce: kumulative Berechnung
var total = scores.reduce((sum, s) => sum + s);
print('BEISPIEL Gesamtpunktzahl: $total');
// fold: kumulative Berechnung mit einem Anfangswert
var avg = scores.fold(0, (sum, s) => sum + s) / scores.length;
print('Durchschnittliche Punktzahl: ${avg.toStringAsFixed(1)}');
// any / every: Existenzprüfung
bool hasFullMark = scores.any((s) => s == 100);
bool allPassed = scores.every((s) => s >= 60);
print('Gibt es eine perfekte Punktzahl? $hasFullMark');
print('Alle bestanden? $allPassed');
}
及格分数: (78, 92, 60, 88) 评级: (不及格, 及格, 及格, 及格, 不及格, 及格) 高分列表: [高分: 92, 高分: 88] EXAMPLE 总分: 418 平均分: 69.7 有满分吗? false 全部及格? false
map() und where() geben ein Iterable zurück (verzögerte Auswertung). Du musst es mit toList() in eine List umwandeln, damit die Berechnung tatsächlich ausgeführt wird. Wenn du nur einmal iterieren musst, kannst du das Iterable direkt verwenden.
Set: Sammlung eindeutiger Elemente
Set ist ähnlich wie List, aber jedes Element in einem Set kann nur einmal vorkommen; Duplikate sind nicht erlaubt.
Set ist ungeordnet, und auf Elemente kann nicht per Index zugegriffen werden.
Beispiel
// Ein Set erstellen (Elemente werden automatisch dedupliziert)
Set<String> tags = {'Dart', 'Flutter', 'Dart', 'EXAMPLE'};
print('Tag-Menge: $tags'); // {Dart, Flutter, EXAMPLE}, das doppelte Dart wurde entfernt
print('Tag-Anzahl: ${tags.length}'); // 3
// Elemente hinzufügen
tags.add('Google');
tags.add('Dart'); // Dart ist bereits vorhanden, es wird nicht erneut hinzugefügt
print('Nach dem Hinzufügen: $tags');
// Elemente löschen
tags.remove('Google');
print('Nach dem Löschen: $tags');
// Prüfen, ob enthalten
print('Enthält EXAMPLE? ${tags.contains('EXAMPLE')}');
// Mengenoperationen
var setA = {1, 2, 3, 4};
var setB = {3, 4, 5, 6};
print('Schnittmenge: ${setA.intersection(setB)}'); // {3, 4}
print('Vereinigung: ${setA.union(setB)}'); // {1, 2, 3, 4, 5, 6}
print('Differenz: ${setA.difference(setB)}'); // {1, 2}
}
标签集合: {Dart, Flutter, EXAMPLE}
标签数量: 3
添加后: {Dart, Flutter, EXAMPLE, Google}
After deletion: {Dart, Flutter, EXAMPLE}
包含 EXAMPLE? true
交集: {3, 4}
并集: {1, 2, 3, 4, 5, 6}
差集: {1, 2}
Der typische Anwendungsfall für Set ist die Deduplizierung. Wenn keine doppelten Elemente benötigt werden, ist die Verwendung von Set viel effizienter als das manuelle Deduplizieren mit List.
Map: Zuordnung von Schlüssel-Wert-Paaren
Map wird verwendet, um Schlüssel-Wert-Paare zu speichern. Jeder Schlüssel entspricht einem Wert.
Schlüssel in einer Map müssen eindeutig sein; Werte können dupliziert werden.
Erstellen und Zugreifen auf Map
Beispiel
// Map mit Literalen erstellen
Map<String, String> siteInfo = {
'name': 'EXAMPLE',
'url': 'https://www.example.com',
'type': 'Programmier-Tutorial',
};
// Wert über Schlüssel abrufen
print('Seitenname: ${siteInfo['name']}');
print('Seiten-URL: ${siteInfo['url']}');
// Zugriff auf einen nicht vorhandenen Schlüssel gibt null zurück
print('Beschreibung: ${siteInfo['description']}'); // null
// Schlüssel-Wert-Paare hinzufügen/ändern
siteInfo['language'] = 'Chinesisch';
siteInfo['name'] = 'example.com'; // Wert eines vorhandenen Schlüssels ändern
print('Nach Aktualisierung: $siteInfo');
// Alle Schlüssel und alle Werte abrufen
print('Alle Schlüssel: ${siteInfo.keys}');
print('Alle Werte: ${siteInfo.values}');
// Prüfen, ob Schlüssel existiert
print('Enthält url-Schlüssel? ${siteInfo.containsKey('url')}');
print('Enthält desc-Schlüssel? ${siteInfo.containsKey('desc')}');
}
站点名称: EXAMPLE
站点 URL: https://www.example.com
描述: null
更新后: {name: example.com, url: https://www.example.com, type: 编程教程, language: 中文}
所有键: (name, url, type, language)
所有值: (example.com, https://www.example.com, 编程教程, 中文)
有 url 键? true
有 desc 键? false
Gängige Map-Operationen
Beispiel
var scores = {
'example': 95,
'Alice': 87,
'Bob': 72,
};
// Über Map iterieren
scores.forEach((name, score) {
print('$name: $score Punkte');
});
// Schlüssel-Wert-Paar löschen
scores.remove('Bob');
print('Nach dem Löschen von Bob: $scores');
// Wert oder Standardwert abrufen
int aliceScore = scores['Alice'] ?? 0;
int eveScore = scores['Eve'] ?? 0; // Falls nicht vorhanden, Standardwert 0 zurückgeben
print('Alice: $aliceScore, Eve: $eveScore');
// putIfAbsent: nur hinzufügen, wenn der Schlüssel nicht vorhanden ist
scores.putIfAbsent('example', () => 100); // Existiert bereits, nicht hinzufügen
scores.putIfAbsent('David', () => 80); // Falls nicht vorhanden, hinzufügen
print('Endstand: $scores');
// Länge abrufen
print('Anzahl der Personen: ${scores.length}');
}
example: 95 分
Alice: 87 分
Bob: 72 分
删除 Bob 后: {example: 95, Alice: 87}
Alice: 87, Eve: 0
最终: {example: 95, Alice: 87, David: 80}
人数: 3
Schlüssel in einer Map können von jedem Typ sein (String, int usw.), aber die Gleichheit von Schlüsseln muss aussagekräftig sein. Wenn benutzerdefinierte Objekte als Schlüssel verwendet werden, müssen Sie sicherstellen, dass == und hashCode korrekt implementiert sind.
Collection-Spread-Operatoren ... und ...?
Der Spread-Operator kann die Elemente einer Collection in eine andere Collection verteilen.
Beispiel
var basics = ['Dart', 'Flutter'];
var advanced = ['Asynchrone Programmierung', 'Zustandsverwaltung'];
// ... Spread-Operator: Elemente aus einer anderen Collection einfügen
var allCourses = ['BEISPIEL Erste Schritte', ...basics, ...advanced];
print('Alle Kurse: $allCourses');
// ...? Null-aware-Spread: überspringen, wenn die Collection null ist
List<String>? optionalList; // Kann null sein
var safeList = ['Erstes Element', ...?optionalList];
print('Sicherer Spread: $safeList'); // Nur das erste Element
optionalList = ['Zusätzlicher Inhalt'];
safeList = ['Erstes Element', ...?optionalList];
print('Non-Null-Spread: $safeList');
}
所有课程: [EXAMPLE 入门, Dart, Flutter, 异步编程, 状态管理] 安全展开: [第一项] 有值展开: [第一项, 额外内容]
if und for in Sammlungen (Kontrollfluss in Sammlungen)
Dart ermöglicht die direkte Verwendung von if und for in Sammlungsliteralen; das ist sehr nützlicher syntaktischer Zucker.
Beispiel
bool showAdmin = true;
// Sammlungs-if: Elemente bedingt einschließen
var menuItems = [
'Startseite',
'Tutorial',
if (showAdmin) 'Admin-Panel', // Nur hinzufügen, wenn die Bedingung wahr ist
'Über',
];
print('Menü: $menuItems');
// for in einer Sammlung: Elemente aus einer anderen Sammlung erzeugen
var numbers = [1, 2, 3];
var doubled = [
for (var n in numbers) n * 2, // Iterieren, um neue Elemente zu erzeugen
];
print(Verdoppelt: $doubled);
// if + for können kombiniert werden
var tags = ['Dart', 'Flutter'];
var links = [
'BEISPIEL Startseite',
for (var tag in tags) 'https://example.com/$tag',
];
print('Links: $links');
}
菜单: [首页, 教程, 管理后台, 关于] 翻倍: [2, 4, 6] 链接: [EXAMPLE 首页, https://example.com/Dart, https://example.com/Flutter]
Vergleich von drei Sammlungen
| Funktionen | Liste | Set | Map |
|---|---|---|---|
| Reihenfolge | Geordnet | Ungeordnet | Ungeordnet (hat aber eine Iterationsreihenfolge) |
| Duplikate erlaubt | Erlaubt | Nicht erlaubt | Schlüssel müssen eindeutig sein, Werte dürfen mehrfach vorkommen |
| Indexzugriff | Unterstützt [] | Nicht unterstützt | Zugriff über Schlüssel [] |
| Typische Szenarien | Geordnete Liste, Sequenz | Deduplizierung, Tag-Sammlung | Schlüssel-Wert-Zuordnung, Konfigurationselemente |
| Literale erstellen | [] | {} | {key: value} |
Hinweise
Sowohl Set als auch Map verwenden{}als Literal.
Der Unterschied ist:
- Map-Verwendungkey: valueForm (mit Doppelpunkt)
- Set schreibt Elemente direkt (ohne Doppelpunkt)
Zum Beispiel:
var map = {'name': 'Tom'}; // Map
var set = {'Tom', 'Jerry'}; // Set
Besonders zu beachten:
var x = {};
Dies erzeugt kein leeres Set; stattdessen leitet Dart es ab als:
Map<dynamic, dynamic>
Da leere geschweifte Klammern den Elementtyp nicht bestimmen können, behandelt Dart sie standardmäßig als Map.
Um ein leeres Set zu erstellen, müssen Sie explizit angeben:
var x = <String>{};
oder
:
Set<String> x = {};Weitere Erweiterungen