Coleções no Dart

I. Três coleções nativas do Dart

O Dart possui três tipos de coleção embutidos por padrão: List, Set e Map;

A limitação de tipo dos elementos internos da coleção é configurada por meio dosGenéricos (Generics).

Tipo de coleçãoCaracterísticas principaisIdentificador literal
ListOrdenada, aceita valores repetidos, acesso por índice[]
SetSem ordem definida, elementos únicos, sem índices{} (é necessário declarar genérico explicitamente para ser reconhecido como Set)
MapArmazena pares chave-valor, chave única, valores podem se repetir{chave: valor}

II. List Lista (vetor ordenado)

1. Definição básica e inferência de tipos

  • No Dart, os vetores são objetos List por natureza, criados com o literal [];
  • O tipo é inferido automaticamente. Exemplo: var list = [1,2,3]List<int>; inserir valor que não seja inteiro causará erro;
  • Suportavírgula no final da lista, não interfere na sintaxe e reduz erros ao copiar e colar: var list = ['Car', 'Boat', 'Plane',];

2. Operações básicas

  1. Regra de índices: iniciam em 0, o último índice válido é list.length - 1;
  2. Leitura / alteração de elementos: list[index], list[index] = novoValor;
  3. Obter o tamanho da lista: propriedade .length;

Exemplo

void main() {
	var list = [1,2,3];
	print(list.length);//Imprime a quantidade de elementos: 3
	print(list[1]);// Imprime o valor 2
	list[1] = 9; //Altera o segundo elemento para 9
	print(list[1]);//Imprime o valor modificado: 9
}Code language: Dart (dart)

3. Lista constante (imutável em tempo de compilação)

Adicione a palavra reservada const antes do literal; não será possível adicionar, remover ou modificar elementos durante a execução:

void main() {
	var constantList = const [1,2,3];
	constantList[1] = 100; // Erro de compilação
}Code language: Dart (dart)
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)Code language: PHP (php)

III. Set Conjunto

Elementos sem ordem definida e valores exclusivos

1. Características centrais do Set

  • Sem ordem: os elementos não possuem índice fixo, não é possível ler ou alterar valores com a sintaxe [índice]
  • Elementos únicos: remove duplicatas automaticamente. Ao adicionar valores repetidos não ocorre erro, mas apenas uma cópia é mantida
  • Identificador literal: chaves curvas {}
  • Restrição de genérico: é possível limitar o armazenamento a um único tipo; inserir tipos diferentes causará erro de compilação ou execução

Diferenciar Set vazio e Map vazio (ponto comum de confusão)

O símbolo {} é interpretado como Map por padrão. Para criar um Set vazio, é obrigatório declarar o genérico explicitamente

void main() {
	// Set vazio do tipo String
	var names = <String>{};
	Set<String> names2 = {}; // Forma equivalente

	// Sem anotação de genérico, Dart classifica como Map<dynamic, dynamic>
	var names3 = {};
}Code language: Dart (dart)
Inferência de tipos
void main() {
	// Inferido automaticamente como Set<String>
	var halogens = {'dog', 'cat', 'horse'};

	// Inferido automaticamente como Set<int>
	var nums = {1, 2, 6, 2}; // O valor duplicado "2" é excluído, resultado final {1,2,6}

	// Tipos misturados, inferido como Set<Object> (não recomendado, perde validação de tipos)
	var mix = {1, "apple"};
}Code language: JavaScript (javascript)

Após a inferência, inserir um elemento de tipo diverso gerará erro

void main() {
  // O literal contém apenas strings, inferido Set<String>
  var animals = {'dog'};
  print(animals.runtimeType); // _CompactLinkedHashSet<String>

  // Adicionar strings do mesmo tipo sem erros
  animals.add('cat');
  animals.add('pig');
  print(animals); // {dog, cat, pig}
  
  // Erro: o método add espera String, mas recebe um valor inteiro
  animals.add(1); 
}Code language: Dart (dart)

2. Adição, exclusão e tamanho

  • Adicionar um único elemento: .add();
  • Adicionar múltiplos elementos de uma vez: .addAll();
  • Obter quantidade total de elementos: .length;
var elements = <String>{};
elements.add('fluorine');
elements.addAll({'chlorine', 'bromine'});
print(elements.length); //3Code language: PHP (php)

3. Set constante

Coloque const antes do literal; não é possível adicionar ou remover elementos:

final constantSet = const {'fluorine', 'chlorine'};
// constantSet.add('helium'); // Gera erroCode language: PHP (php)

IV. Map Mapa (pares chave-valor)

1. Características básicas
  • Armazena dados no formato de pares Chave-Valor;
  • A chave é única em todo o mapa, os valores podem se repetir;
  • Tanto chave quanto valor aceitam qualquer tipo de objeto;
  • Formato literal: {chave: valor};
  • Inferência automática de tipos:
void main() {
	var gifts = {'first': 'partridge'}; // Inferido automaticamente como Map<String, String> 
	
	var nobleGases = {2: 'helium'}; // Inferido automaticamente como Map<int, String>
}Code language: Dart (dart)
2. Duas formas de criação
  • Criação via literal
var gifts = {'first': 'partridge'};  Code language: Dart (dart)
  • Criação com construtor Map (a palavra-chave new pode ser omitida)
// Sintaxe com construtor
var gifts = Map<String, String>();
gifts['first'] = 'partridge';Code language: JavaScript (javascript)
3. Adicionar, consultar e tamanho
  1. Adicionar / sobrescrever par chave-valor: map[chave] = valor;
  2. Buscar valor por chave: map[chave]; retorna null se a chave não existir;
  3. Obter total de pares chave-valor: .length;
var gifts = {'first': 'partridge'};
gifts['fourth'] = 'calling birds'; // Adiciona novo par
print(gifts['first']); // Consulta valor
print(gifts['fifth']);// Consulta chave inexistente
print(gifts.length); // Obtém quantidade de pares Code language: PHP (php)
4. Map constante

Adicione const antes do literal; os pares chave-valor não podem ser alterados:

final constantMap = const {2: 'helium', 10: 'neon'};
// constantMap[2] = 'Helium'; // Gera erroCode language: Dart (dart)

V. Elementos avançados em literais de coleção

Dentro dos literais de coleção há suporte para diversas sintaxes especiais, divididas em dois grupos: elementos básicos e elementos de fluxo de controle, com objetivo de simplificar a montagem de coleções.

  1. Elementos básicos: expressões únicas, pares chave-valor, elementos seguros contra null
  2. Elementos de fluxo de controle: operador spread, condicional if, laço for, combinações aninhadas

1. Elementos de expressão comum

Forma mais simples de uso: escreva diretamente uma expressão, e seu resultado será inserido na coleção. No exemplo abaixo o segundo elemento é o cálculo de 2 * 3, a saída final é [1, 6, text]

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

2. Elementos chave-valor

Exclusivo para literais Map, formato expressãoChave : expressãoValor. No exemplo a seguir tanto a chave quanto o valor do primeiro item são gerados por expressões matemáticas.

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

3. Elementos seguros contra null (Dart ≥3.8)

Sintaxe ?expressão: apenas insere o valor na coleção se o resultado da expressão não for null; se for null, o item é ignorado completamente

Uso em List: a é null, por isso não aparece no resultado final, sem erros

int? a = null;
int? b = 3;
var items = [1, ?a, ?b, 5]; // [1, 3, 5]Code language: JavaScript (javascript)

Uso em Map (o símbolo ? pode ser aplicado tanto na chave quanto no valor)

String? k = null;
int? v = null;
var m = {?k: ?v}; // Se chave ou valor forem null, todo o par é descartado
Code language: JavaScript (javascript)

4. Operador Spread (expansão)

① Expansão normal ...

Expande todos os elementos de uma coleção iterável para inseri-los no local desejado. Não é possível expandir uma coleção null

var a = [1,2,3];
var items = [0, ...a, 4]; // [0,1,2,3,4]Code language: JavaScript (javascript)
② Expansão segura contra null ...?

Compatível com coleções que aceitam null: se a coleção for null ela é ignorada sem lançar exceção;

Se a coleção não for null mas conter elementos null internos, esses valores null serão mantidos

List<int>? a = null;
var b = [1, null, 3];
var items = [0, ...?a, ...?b, 4]; // [0, 1, null, 3, 4]Code language: PHP (php)

Regra obrigatória: coleções com tipo anulável devem usar ...?, caso contrário ocorrerá erro de compilação.

5. Elemento If (condicional)

É possível escrever blocos if diretamente dentro da coleção; o conteúdo só é inserido se a condição for verdadeira. Suporta validação booleana, correspondência de padrão if-case e else

Validação booleana básica
void main() {
	bool flag = true;
    var list = [0, if(flag) 1 else 99, 2];
	print(list); //[0, 1, 2]
}Code language: Dart (dart)
if-case correspondência de padrão (desconstrução de tipos e vetores)
void main() {
	Object data = 123;
	var info = [
	  if(data case int i) 'Número: $i',
	  if(data case String s) 'Texto: $s'
	];
	print(info); //[Número: 123]
}Code language: Dart (dart)

Como data é do tipo int, apenas o trecho “Número: 123” é inserido, o trecho de texto é ignorado

6. Elemento For (laço de repetição)

Insira laços for diretamente dentro da coleção para gerar múltiplos elementos. Suporta for-in e o laço tradicional de três parâmetros

var nums = [2,3,4];

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

// Laço for de três parâmetros
var list2 = [1, for(var x=5; x>2; x--) x, 7]; // [1,5,4,3,7]Code language: JavaScript (javascript)

7. Fluxos de controle aninhados

if, for e operador spread podem ser aninhados em múltiplos níveis livremente, com funcionalidade equivalente às compreensões de lista de outras linguagens

Exemplo: manter apenas números pares

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]Code language: JavaScript (javascript)

Exemplo: for aninhado + if + operador spread

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]
}Code language: Dart (dart)

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *