Kollektionen in Dart

I. Die drei integrierten Kollektionen von Dart

Dart verfügt über drei nativ integrierte Kollektionstypen: List, Set und Map;

Die Typbegrenzung der Elemente einer Kollektion wird mithilfe vonGenerika (Generics) festgelegt.

KollektionstypHauptmerkmaleLiteral-Kennzeichen
ListGeordnet, Duplikate erlaubt, Zugriff per Index[]
SetUngeordnet, eindeutige Elemente, keine Indizes{} (Generika muss explizit angegeben werden, damit es als Set erkannt wird)
MapSpeichert Schlüssel-Wert-Paare, Schlüssel eindeutig, Werte können doppelt vorkommen{schlüssel: wert}

II. List Liste (geordnetes Array)

1. Grunddefinition und Typinferenz

  • Arrays in Dart sind von Natur aus List-Objekte und werden mit dem Literal [] erstellt;
  • Der Typ wird automatisch abgeleitet. Beispiel: var list = [1,2,3]List<int>; das Einfügen eines nicht ganzzahligen Werts löst einen Fehler aus;
  • Unterstützt dasnachgestellte Komma, es beeinträchtigt die Syntax nicht und reduziert Kopier-Einfüge-Fehler: var list = ['Car', 'Boat', 'Plane',];

2. Grundoperationen

  1. Index-Regel: Indizes beginnen bei 0, der letzte gültige Index lautet list.length - 1;
  2. Lesen / Ändern von Elementen: list[index], list[index] = neuerWert;
  3. Abfragen der Länge: Eigenschaft .length;

Beispiel

void main() {
	var list = [1,2,3];
	print(list.length);//Gibt die Anzahl der Elemente aus: 3
	print(list[1]);// Gibt den Wert 2 aus
	list[1] = 9; //Ändert das zweite Element zu 9
	print(list[1]);//Gibt den geänderten Wert 9 aus
}

3. Konstante Liste (kompilierzeitunveränderlich)

Stellen Sie das Schlüsselwort const vor das Literal: Zur Laufzeit können keine Elemente hinzugefügt, gelöscht oder verändert werden:

void main() {
	var constantList = const [1,2,3];
	constantList[1] = 100; // Kompilierfehler
}
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
Unhandled exception:
Unsupported operation: Cannot modify an unmodifiable list
#0      UnmodifiableListMixin.[]= (dart:_internal/list.dart:89:5)
#1      main (file:///D:/dartdemo/firstdart/bin/firstdart.dart:4:14)
#2      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:314:19)
#3      _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:193:12)

III. Set Menge

Ungeordnete Sammlung mit eindeutigen Elementen

1. Kernmerkmale von Set

  • Ungeordnet: Elemente besitzen keinen festen Index, Lesen und Ändern per [Index] ist nicht möglich
  • Eindeutige Elemente: Duplikate werden automatisch entfernt. Das Hinzufügen identischer Werte löst keinen Fehler aus, es bleibt jedoch nur eine Kopie erhalten
  • Literal-Kennzeichen: Geschweifte Klammern {}
  • Generika-Beschränkung: Der Typ kann auf eine einzelne Sorte festgelegt werden; Einfügen anderer Typen erzeugt Kompilier- oder Laufzeitfehler

Unterscheidung leeres Set und leeres Map (häufige Verwechslung)

Das Symbol {} wird standardmäßig als Map interpretiert. Um ein leeres Set zu erstellen, muss das Generikum explizit angegeben werden

void main() {
	// Leeres Set vom Typ String
	var names = <String>{};
	Set<String> names2 = {}; // Äquivalente Schreibweise

	// Ohne Generika-Annotation erkennt Dart es als Map<dynamic, dynamic>
	var names3 = {};
}
Typinferenz
void main() {
	// Automatisch abgeleitet als Set<String>
	var halogens = {'dog', 'cat', 'horse'};

	// Automatisch abgeleitet als Set<int>
	var nums = {1, 2, 6, 2}; // Der doppelte Wert 2 wird automatisch gelöscht, Ergebnis {1,2,6}

	// Gemischte Typen → Set<Object> (nicht empfohlen, Typüberprüfung geht verloren)
	var mix = {1, "apple"};
}

Nach der Typableitung löst das Einfügen eines Elements abweichenden Typs einen Fehler aus

void main() {
  // Das Literal enthält nur Zeichenketten → Inferenz Set<String>
  var animals = {'dog'};
  print(animals.runtimeType); // _CompactLinkedHashSet<String>

  // Hinzufügen von Zeichenketten gleichen Typs ohne Fehler
  animals.add('cat');
  animals.add('pig');
  print(animals); // {dog, cat, pig}
  
  // Fehler: Die Methode add erwartet String, erhält aber einen Integer
  animals.add(1); 
}

2. Hinzufügen, Entfernen und Länge

  • Einzelnes Element hinzufügen: .add();
  • Mehrere Elemente auf einmal hinzufügen: .addAll();
  • Gesamtzahl der Elemente abfragen: .length;
var elements = <String>{};
elements.add('fluorine');
elements.addAll({'chlorine', 'bromine'});
print(elements.length); //3

3. Konstante Set

Stellen Sie const vor das Literal: Hinzufügen und Löschen von Elementen ist verboten:

final constantSet = const {'fluorine', 'chlorine'};
// constantSet.add('helium'); // Löst einen Fehler aus

IV. Map Abbildung (Schlüssel-Wert-Paare)

1. Grundmerkmale
  • Speichert Daten als Paare Schlüssel-Wert;
  • Der Schlüssel ist innerhalb der gesamten Abbildung eindeutig, Werte dürfen doppelt vorkommen;
  • Sowohl Schlüssel als auch Wert akzeptieren beliebige Objekttypen;
  • Literal-Format: {schlüssel: wert};
  • Automatische Typinferenz:
void main() {
	var gifts = {'first': 'partridge'}; // Automatisch abgeleitet als Map<String, String> 
	
	var nobleGases = {2: 'helium'}; // Automatisch abgeleitet als Map<int, String>
}
2. Zwei Erstellungsweisen
  • Erstellung per Literal
var gifts = {'first': 'partridge'};  
  • Erstellung mit Map-Konstruktor (das Schlüsselwort new kann weggelassen werden)
// Konstruktor-Schreibweise
var gifts = Map<String, String>();
gifts['first'] = 'partridge';
3. Hinzufügen, Abfragen und Länge
  1. Paar hinzufügen / überschreiben: map[schlüssel] = wert;
  2. Wert per Schlüssel abfragen: map[schlüssel]; gibt null zurück, falls der Schlüssel nicht existiert;
  3. Gesamtzahl der Schlüssel-Wert-Paare abfragen: .length;
var gifts = {'first': 'partridge'};
gifts['fourth'] = 'calling birds'; // Neues Paar hinzufügen
print(gifts['first']); // Wert abfragen
print(gifts['fifth']);// Nicht vorhandenen Schlüssel abfragen
print(gifts.length); // Anzahl der Paare abfragen 
4. Konstante Map

Stellen Sie const vor das Literal: Schlüssel-Wert-Paare können nicht verändert werden:

final constantMap = const {2: 'helium', 10: 'neon'};
// constantMap[2] = 'Helium'; // Löst einen Fehler aus

V. Erweiterte Elemente in Kollektionsliteralen

Innerhalb von Kollektionsliteralen werden zahlreiche Sonder-Syntaxen unterstützt, aufgeteilt in zwei Gruppen: Basis-Elemente und Steuerfluss-Elemente, um das Erstellen von Kollektionen zu vereinfachen.

  1. Basis-Elemente: Einfache Ausdrücke, Schlüssel-Wert-Paare, Null-sichere Elemente
  2. Steuerfluss-Elemente: Spread-Operator, If-Bedingung, For-Schleife, verschachtelte Kombinationen

1. Einfache Ausdruckselemente

Einfachste Schreibweise: Schreiben Sie direkt einen Ausdruck, dessen Ergebnis wird in die Kollektion eingefügt. Im folgenden Beispiel ist das zweite Element das Ergebnis von 2 * 3, das Endergebnis lautet [1, 6, text]

void main() {
	var list = [1, 2 * 3, 'text'];
	print(list); //[1, 6, text]
}

2. Schlüssel-Wert-Elemente

Nur für Map-Literale, Format ausdruckSchlüssel : ausdruckWert. Im Beispiel unten werden Schlüssel und Wert des ersten Elements jeweils per Ausdruck berechnet.

void main() {
	var map = {1+1: 3*8, 'name': 'apple'};
	print(map); //{2: 24, name: apple}
}

3. Null-sichere Elemente (Dart ≥3.8)

Syntax ?Ausdruck: Das Element wird nur eingefügt, wenn der Ausdruck nicht null ist; bei null wird es vollständig ignoriert

Einsatz bei List: a ist null, also wird es am Ende nicht eingefügt, ohne Fehler

int? a = null;
int? b = 3;
var items = [1, ?a, ?b, 5]; // [1, 3, 5]

Einsatz bei Map (das Zeichen ? kann sowohl vor Schlüssel als auch vor Wert platziert werden)

String? k = null;
int? v = null;
var m = {?k: ?v}; // Wenn Schlüssel ODER Wert null ist, wird das gesamte Paar verworfen

4. Spread-Operator (Aufteiloperator)

① Normaler Spread ...

Teilt alle Elemente einer iterierbaren Kollektion auf und fügt sie ein; eine null-Kollektion kann nicht aufgeteilt werden

var a = [1,2,3];
var items = [0, ...a, 4]; // [0,1,2,3,4]
② Null-sicherer Spread ...?

Kompatibel mit nullable Kollektionen: Ist die Kollektion null, wird sie ohne Fehler ignoriert;

Ist die Kollektion nicht null, enthält aber interne null-Elemente, bleiben diese null-Werte erhalten

List<int>? a = null;
var b = [1, null, 3];
var items = [0, ...?a, ...?b, 4]; // [0, 1, null, 3, 4]

Zwingende Regel: Kollektionen mit nullable Typ müssen ...? verwenden, sonst entsteht ein Kompilierfehler.

5. If-Element (Bedingung)

Sie können einen If-Block direkt innerhalb der Kollektion schreiben; der Inhalt wird nur eingefügt, wenn die Bedingung wahr ist. Unterstützt boolesche Prüfung, if-case-Musterabgleich und else

Einfache boolesche Prüfung
void main() {
	bool flag = true;
    var list = [0, if(flag) 1 else 99, 2];
	print(list); //[0, 1, 2]
}
if-case Musterabgleich (Typ- und Array-Dekomposition)
void main() {
	Object data = 123;
	var info = [
	  if(data case int i) 'Zahl: $i',
	  if(data case String s) 'Text: $s'
	];
	print(info); //[Zahl: 123]
}

Da data vom Typ int ist, wird nur „Zahl: 123“ eingefügt, der Text-Zweig wird ignoriert

6. For-Element (Schleife)

Schreiben Sie eine For-Schleife direkt in die Kollektion, um mehrere Elemente per Iteration zu erzeugen. Unterstützt for-in und die klassische Dreiteiler-Schleife

var nums = [2,3,4];

// for-in
var list1 = [1, for(var n in nums) n*n, 7]; // [1,4,9,16,7]

// Dreiteiler-For-Schleife
var list2 = [1, for(var x=5; x>2; x--) x, 7]; // [1,5,4,3,7]

7. Verschachtelte Steuerflüsse

If, For und Spread-Operator können frei auf mehreren Ebenen verschachtelt werden, funktional identisch mit List-Comprehensions anderer Sprachen

Beispiel: Nur gerade Zahlen behalten

var numbers = [1,2,3,4,5,6];
var items = [
  0,
  for(var n in numbers)
    if(n.isEven) n,
  8
]; // [0,2,4,6,8]

Beispiel: Verschachteltes For + If + Spread-Operator

void main() {
	var ys = [1,2,3];
	var nest = [
	  ...[
		for(var x=0;x<2;x++)
		  for(var y in ys)
			if(x<y) x+y*10
	  ]
	];
	print(nest); //[10, 20, 30, 21, 31]
}

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert