Collections
Os Collections são estruturas usadas para guardar vários valores. Em Dart, as principais collections são:
| Estrutura | Uso |
|---|---|
List | Lista ordenada de valores |
Map | Dados em chave e valor |
Set | Conjunto de valores únicos |
O Dart tem suporte nativo para List, Set e Map. Os arrays são objetos do tipo List, então normalmente chamamos de lista mesmo.
Já vimos um pouco sobre Collections na sessão Principais tipos de dados.
List
Uma List é uma lista ordenada de valores. Ela é parecida com list em Python ou array em JavaScript.
void main() {
List<String> usuarios = ['Ana', 'Fulano', 'Carlos'];
print(usuarios);
}
Acessar item da lista
As Listas usam índices e o primeiro item fica sempre na posição 0.
void main() {
List<String> usuarios = ['Ana', 'Fulano', 'Carlos'];
print(usuarios[0]);
print(usuarios[1]);
print(usuarios[2]);
}
Adicionar item
Para dicionar um item numa lista, usamos o método add.
void main() {
List<String> usuarios = ['Ana', 'Fulano'];
usuarios.add('Carlos');
print(usuarios);
}
Também pode adicionar vários itens com o método addAll.
void main() {
List<String> usuarios = ['Ana'];
usuarios.addAll(['Fulano', 'Carlos']);
print(usuarios);
}
Alterar item
Para alterar um item, precisamos usar o índice.
void main() {
List<String> usuarios = ['Ana', 'Fulano', 'Carlos'];
usuarios[1] = 'Beatriz';
print(usuarios);
}
Remover item
Para remover um item, usamos o método remove.
void main() {
List<String> usuarios = ['Ana', 'Fulano', 'Carlos'];
usuarios.remove('Fulano');
print(usuarios);
}
Também podemos usar o método removeAt para remover baseado no índice.
void main() {
List<String> usuarios = ['Ana', 'Fulano', 'Carlos'];
usuarios.removeAt(0);
print(usuarios);
}
Buscar item
Para buscar um item, baseado no valor, devemos usar o método contains. Com ele, podemos verificar se um valor existe.
void main() {
List<String> usuarios = ['Ana', 'Fulano', 'Carlos'];
bool existe = usuarios.contains('Fulano');
print(existe);
}
O valor retornado será True ou False.
Também podemos usar o método indexOf para encontrar a posição.
void main() {
List<String> usuarios = ['Ana', 'Fulano', 'Carlos'];
int posicao = usuarios.indexOf('Carlos');
print(posicao);
}
Se o item não existir, o método indexOf retorna -1.
Percorrer lista
Podemos percorrer uma lista com o for in:
void main() {
List<String> usuarios = ['Ana', 'Fulano', 'Carlos'];
for (String usuario in usuarios) {
print('Usuário: $usuario');
}
}
Também podemos usar o forEach:
void main() {
List<String> usuarios = ['Ana', 'Fulano', 'Carlos'];
usuarios.forEach((usuario) {
print('Usuário: $usuario');
});
}
Ou apenas usando o for com índice:
void main() {
List<String> usuarios = ['Ana', 'Fulano', 'Carlos'];
for (int i = 0; i < usuarios.length; i++) {
print('${i + 1}. ${usuarios[i]}');
}
}
Uma dica é, use for in quando precisa do valor. Mas se precisar da posição na lista, use o for com índice.
Map
O Map guarda dados no formato chave e valor. É parecido com dict em Python ou objeto simples em JavaScript.
void main() {
Map<String, String> usuario = {
'nome': 'Fulano',
'email': 'Fulano@example.com',
};
print(usuario);
}
A primeira String é o tipo da chave e a segunda String é o tipo do valor.
Acessar valor
Para ver o valor de uma chave, basta chamar o Map fornecendo o nome da chave:
void main() {
Map<String, String> usuario = {
'nome': 'Fulano',
'email': 'Fulano@example.com',
};
print(usuario['nome']);
print(usuario['email']);
}
Adicionar valor
Para adicionar uma chave/valor, basta fazer o Map receber um valor, mas fornecendo uma chave que não exista no Map:
void main() {
Map<String, String> usuario = {
'nome': 'Fulano',
};
usuario['email'] = 'Fulano@example.com';
print(usuario);
}
Alterar valor
Se a chave já existe, a atribuição altera o valor.
void main() {
Map<String, String> usuario = {
'nome': 'Fulano',
'email': 'Fulano@example.com',
};
usuario['email'] = 'novo@example.com';
print(usuario);
}
Remover valor
Para remover um valor, usamos o método remove.
void main() {
Map<String, String> usuario = {
'nome': 'Fulano',
'email': 'Fulano@example.com',
};
usuario.remove('email');
print(usuario);
}
Verificar se uma chave existe
Podemos usar o método containsKey para verificar se uma chave existe dentro do Map. O resultado será true ou false.
void main() {
Map<String, String> usuario = {
'nome': 'Fulano',
'email': 'Fulano@example.com',
};
print(usuario.containsKey('email'));
print(usuario.containsKey('telefone'));
}
Verificar se um valor existe
Podemos usar o método containsValue para verificar se um valor existe dentro do Map. O resultado será true ou false.
void main() {
Map<String, String> usuario = {
'nome': 'Fulano',
'email': 'Fulano@example.com',
};
print(usuario.containsValue('Fulano'));
}
Percorrer Map
Podemos percorrer um Map com o forEach:
void main() {
Map<String, String> usuario = {
'nome': 'Fulano',
'email': 'Fulano@example.com',
};
usuario.forEach((chave, valor) {
print('$chave: $valor');
});
}
Também podemos usar o entries:
void main() {
Map<String, String> usuario = {
'nome': 'Fulano',
'email': 'Fulano@example.com',
};
for (var entrada in usuario.entries) {
print('${entrada.key}: ${entrada.value}');
}
}
O entries permite percorrer o Map pegando a chave e o valor ao mesmo tempo. Quando chamado usuario.entries (ou seja, nome_do_map.entries), ele vai retornar todos os pares do Map. Cada item percorrido é uma entrada do mapa.
Essa entrada possui duas partes, uma é a var_name.key, que representa a chave. E a segunda é a var_name.value, que representa o valor.
keys
O método keys retorna somente as chaves do Map.
void main() {
Map<String, String> usuario = {
'nome': 'Fulano',
'email': 'fulano@example.com',
};
print(usuario.keys);
}
values
O método values retorna somente os valores do Map.
void main() {
Map<String, String> usuario = {
'nome': 'Fulano',
'email': 'fulano@example.com',
};
print(usuario.values);
}
Map com valores de tipos diferentes
Quando os valores têm tipos diferentes, devemos usar Object, ficando assim:
void main() {
Map<String, Object> usuario = {
'nome': 'Fulano',
'idade': 27,
'ativo': true,
};
print(usuario['nome']);
print(usuario['idade']);
print(usuario['ativo']);
}
Caso você precise usar o valor como tipo específico, faça cast:
void main() {
Map<String, Object> usuario = {
'nome': 'Fulano',
'idade': 27,
};
String nome = usuario['nome'] as String;
int idade = usuario['idade'] as int;
print(nome);
print(idade);
}
Quando fazemos usuario['nome'], o Dart não sabe que o valor dessa chave é uma String, ele só sabe que pode ser um Object ou null. Por isso, às vezes precisamos fazer cast.
O Cast é como dizer ao Dart "Trate este valor como este tipo específico". No exemplo que usamos acima:
String nome = usuario['nome'] as String;
O valor da chave nome deve ser tratado como String. Isso é necessário em exemplos como o abaixo:
void main() {
Map<String, Object> usuario = {
'nome': 'Fulano',
'idade': 27,
};
print(usuario['nome'].toUpperCase());
}
O exemplo acima vai dar erro, já que usuario['nome'] é tratado como Object e não como String (o método toUpperCase só funciona com strings).
Set
O Set é igual a uma List em essência, mas diferente no comportamento e uso. Ele é usado para guardar valores únicos, nunca haverá valores repetidos, se você tentar adicionar um valor repetido, ele não será duplicado.
void main() {
Set<String> permissoes = {'read', 'write', 'read'};
print(permissoes);
}
O valor read apareceu duas vezes no código, mas ficou apenas uma vez no Set.
Adicionar item
Para dicionar um item numa lista, usamos o método add.
void main() {
Set<String> permissoes = {'read'};
permissoes.add('write');
permissoes.add('admin');
print(permissoes);
}
Remover item
Para remover um item, usamos o método remove.
void main() {
Set<String> permissoes = {'read', 'write', 'admin'};
permissoes.remove('admin');
print(permissoes);
}
Buscar item
Para buscar um item, baseado no valor, devemos usar o método contains. Com ele, podemos verificar se um valor existe. O valor retornado será true ou false.
void main() {
Set<String> permissoes = {'read', 'write'};
print(permissoes.contains('read'));
print(permissoes.contains('admin'));
}
Percorrer Set
Podemos percorrer um Set com o for in:
void main() {
Set<String> permissoes = {'read', 'write', 'admin'};
for (String permissao in permissoes) {
print('Permissão: $permissao');
}
}
Alterar item em Set
No Set, não é possível altera um item por índice, porque ele não trabalha como uma Lista (como eu disse, parecido na essêncial, mas diferente no comportamento e uso). Então, para que possamos "alterar", devemos remover o valor antigo e adicionar um novo.
void main() {
Set<String> permissoes = {'read', 'write'};
permissoes.remove('write');
permissoes.add('edit');
print(permissoes);
}
Convertendo List para Set
Isso é útil para remover duplicados. Para converter, devemos usar o método toSet.
void main() {
List<String> usuarios = ['Ana', 'Fulano', 'Ana'];
Set<String> usuariosUnicos = usuarios.toSet();
print(usuariosUnicos);
}
Convertendo Set para List
Para converter, devemos usar o método toList.
void main() {
Set<String> permissoes = {'read', 'write'};
List<String> listaPermissoes = permissoes.toList();
print(listaPermissoes);
}
Convertendo Map para lista de chaves
Para converter, devemos usar o método toList.
void main() {
Map<String, String> usuario = {
'nome': 'Fulano',
'email': 'Fulano@example.com',
};
List<String> chaves = usuario.keys.toList();
print(chaves);
}
Convertendo Map para lista de valores
Para converter, devemos usar o método toList.
void main() {
Map<String, String> usuario = {
'nome': 'Fulano',
'email': 'Fulano@example.com',
};
List<String> valores = usuario.values.toList();
print(valores);
}
Métodos úteis
Deixei essa parte para falar sobre alguns métodos que podem ser bem úteis. Os métodos abaixo funcionam com as principais collections explicadas acima (List, Map e Set).
length
Mostra a quantidade de itens.
void main() {
List<String> usuarios = ['Ana', 'Fulano'];
print(usuarios.length);
}
isEmpty
Verifica se está vazio. Retorna true ou false.
void main() {
List<String> usuarios = [];
print(usuarios.isEmpty);
}
isNotEmpty
Verifica se não está vazio. Retorna true ou false.
void main() {
List<String> usuarios = ['Ana'];
print(usuarios.isNotEmpty);
}
clear
Remove todos os itens.
void main() {
List<String> usuarios = ['Ana', 'Fulano'];
usuarios.clear();
print(usuarios);
}