Collections
Dart has built-in support for list, set, and map collections. To learn more about configuring the types collections contain, check out Generics.
Lists
#Perhaps the most common collection in nearly every programming language is the array, or ordered group of objects. In Dart, arrays are List
objects, so most people just call them lists.
Dart list literals are denoted by a comma-separated list of elements enclosed in square brackets ([]
). Each element is usually an expression. Here's a simple Dart list:
var list = [1, 2, 3];
You can add a comma after the last item in a Dart collection literal. This trailing comma doesn't affect the collection, but it can help prevent copy-paste errors.
var list = ['Car', 'Boat', 'Plane'];
Lists use zero-based indexing, where 0 is the index of the first element and list.length - 1
is the index of the last element. You can get a list's length using the .length
property and access a list's elements using the subscript operator ([]
):
var list = [1, 2, 3];
assert(list.length == 3);
assert(list[1] == 2);
list[1] = 1;
assert(list[1] == 1);
To create a list that's a compile-time constant, add const
before the list literal:
var constantList = const [1, 2, 3];
// constantList[1] = 1; // This line will cause an error.
For more information about lists, refer to the Lists section of the dart:core
documentation.
Sets
#A set in Dart is an unordered collection of unique elements. Dart support for sets is provided by set literals and the Set
type.
Here is a simple Dart set, created using a set literal:
var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};
To create an empty set, use {}
preceded by a type argument, or assign {}
to a variable of type Set
:
var names = <String>{};
// Set<String> names = {}; // This works, too.
// var names = {}; // Creates a map, not a set.
Add items to an existing set using the add()
or addAll()
methods:
var elements = <String>{};
elements.add('fluorine');
elements.addAll(halogens);
Use .length
to get the number of items in the set:
var elements = <String>{};
elements.add('fluorine');
elements.addAll(halogens);
assert(elements.length == 5);
To create a set that's a compile-time constant, add const
before the set literal:
final constantSet = const {
'fluorine',
'chlorine',
'bromine',
'iodine',
'astatine',
};
// constantSet.add('helium'); // This line will cause an error.
For more information about sets, refer to the Sets section of the dart:core
documentation.
Maps
#In a map, each element is a key-value pair. Each key within a pair is associated with a value, and both keys and values can be any type of object. Each key can occur only once, although the same value can be associated with multiple different keys. Dart support for maps is provided by map literals and the Map
type.
Here are a couple of simple Dart maps, created using map literals:
var gifts = {
// Key: Value
'first': 'partridge',
'second': 'turtledoves',
'fifth': 'golden rings',
};
var nobleGases = {2: 'helium', 10: 'neon', 18: 'argon'};
You can create the same objects using a Map constructor:
var gifts = Map<String, String>();
gifts['first'] = 'partridge';
gifts['second'] = 'turtledoves';
gifts['fifth'] = 'golden rings';
var nobleGases = Map<int, String>();
nobleGases[2] = 'helium';
nobleGases[10] = 'neon';
nobleGases[18] = 'argon';
Add a new key-value pair to an existing map using the subscript assignment operator ([]=
):
var gifts = {'first': 'partridge'};
gifts['fourth'] = 'calling birds'; // Add a key-value pair
Retrieve a value from a map using the subscript operator ([]
):
var gifts = {'first': 'partridge'};
assert(gifts['first'] == 'partridge');
If you look for a key that isn't in a map, you get null
in return:
var gifts = {'first': 'partridge'};
assert(gifts['fifth'] == null);
Use .length
to get the number of key-value pairs in the map:
var gifts = {'first': 'partridge'};
gifts['fourth'] = 'calling birds';
assert(gifts.length == 2);
To create a map that's a compile-time constant, add const
before the map literal:
final constantMap = const {2: 'helium', 10: 'neon', 18: 'argon'};
// constantMap[2] = 'Helium'; // This line will cause an error.
For more information about maps, refer to the Maps section of the dart:core
documentation.
Collection elements
#A collection literal contains a series of elements. During runtime, each element is evaluated, producing zero or more values that are then inserted into the resulting collection. These elements fall into two main categories: leaf elements and control flow elements.
Leaf element: Inserts an individual item into a collection literal.
Expression element: Evaluates a single expression and inserts the resulting value into the collection.
Map entry element: Evaluates a pair of key and value expressions and inserts the resulting entry into the collection.
Control flow element: Conditionally or iteratively adds zero or more values to the surrounding collection.
Spread element: Iterates over a given sequence (collection expression) and inserts all of the resulting values into the surrounding collection.
Null-aware spread element: Similar to the spread element, but allows the collection to be
null
and inserts nothing if it is.If element: Conditionally evaluates an inner element based on given a condition expression, and optionally evaluates another
else
element if the condition is false.For element: Iterates and repeatedly evaluates a given inner element, inserting zero or more resulting values.
To learn more about collection elements, see the following sections.
Expression elements
#An expression element evaluates a single expression and inserts the resulting value into a collection. This expression can encompass various constructs like literals, variables, operators, function calls, and constructor calls.
An expression element has this syntax in a collection:
<expression>
Map entry elements
#A map entry element evaluates a pair of key and value expressions and inserts the resulting entry into a collection. Both the key and the value within this pair can be expressions.
A map entry element has this syntax in a collection:
<key_expression>: <value_expression>
Spread elements
#The spread element iterates over a given sequence and inserts all of the resulting values into the surrounding collection.
A spread element has the following syntax in a collection. The sequence expression can represent any expression that evaluates to an object that implements Iterable
:
...<sequence_expression>
In the following example, the elements in a list called a
are added to a list called items
.
var a = [1, 2, null, 4];
var items = [0, ...a, 5]; // [0, 1, 2, null, 4, 5]
If you are spreading an expression that might evaluate to null
and you want to ignore the null
(and insert no elements), use a null-aware spread element.
To learn more about the spread operator, see Spread operator.
Null-aware spread elements
#The null-aware spread element is similar to the spread element, but allows the collection to be null
and inserts nothing if it is.
A null-aware spread element has this syntax in a collection:
...?<sequence_expression>
In the following example, a list called a
is ignored because it's null, but the elements in a list called b
are added to a list called items
. Notice that if a collection itself is not null
, but it contains elements that are, those null
elements are still added to the result.
List<int>? a = null;
var b = [1, null, 3];
var items = [0, ...?a, ...?b, 4]; // [0, 1, null, 3, 4]
Because of null safety, you can't perform a spread operation (...
) on a value that might be null. The following example produces a compile-time error because the extraOptions
parameter is nullable and the spread operator used on extraOptions
is not null-aware.
List<String> buildCommandLine(
String executable,
List<String> options, [
List<String>? extraOptions,
]) {
return [
executable,
...options,
...extraOptions, // <-- Error
];
}
// Usage:
// buildCommandLine('dart', ['run', 'my_script.dart'], null);
// Result:
// Compile-time error
If you want to spread a nullable collection, use a null-aware spread element. The following example is valid because the null-aware spread operator is used on extraOptions
.
List<String> buildCommandLine(
String executable,
List<String> options, [
List<String>? extraOptions,
]) {
return [
executable,
...options,
...?extraOptions, // <-- OK now.
];
}
// Usage:
// buildCommandLine('dart', ['run', 'my_script.dart'], null);
// Result:
// [dart, run, my_script.dart]
To learn more about the null-aware spread operator, see Spread operator.
If elements
#An if
element conditionally evaluates an inner element based on given a condition expression, and optionally evaluates another else
element if the condition is false.
The if
element has a few syntax variations:
// If the bool expression is true, include the result.
if (<bool_expression>) <result>
// If the expression matches the pattern, include the result.
if (<expression> case <pattern>) <result>
// If the operation resolves as true, include the first
// result, otherwise, include the second result.
if (<bool_expression>) <result> else <result>
// If the operation resolves as true, include the first
// result, otherwise, include the second result.
if (<expression> case <pattern>) <result> else <result>
The following examples illustrate various ways that you can use an if
element inside of a collection with a boolean expression:
var includeItem = true;
var items = [0, if (includeItem) 1, 2, 3]; // [0, 1, 2, 3]
var includeItem = true;
var items = [0, if (!includeItem) 1, 2, 3]; // [0, 2, 3]
var name = 'apple';
var items = [0, if (name == 'orange') 1 else 10, 2, 3]; // [0, 10, 2, 3]
var name = 'apple';
var items = [
0,
if (name == 'kiwi') 1 else if (name == 'pear') 10,
2,
3,
]; // [0, 2, 3]
The following examples illustrate various ways that you can use an if
element with a case
part inside of a collection:
Object data = 123;
var typeInfo = [
if (data case int i) 'Data is an integer: $i',
if (data case String s) 'Data is a string: $s',
if (data case bool b) 'Data is a boolean: $b',
if (data case double d) 'Data is a double: $d',
]; // [Data is an integer: 123, Data is a double: 123]
var word = 'hello';
var items = [
1,
if (word case String(length: var wordLength)) wordLength,
3,
]; // [1, 5, 3]
var orderDetails = ['Apples', 12, ''];
var summary = [
'Product: ${orderDetails[0]}',
if (orderDetails case [_, int qty, _]) 'Quantity: $qty',
if (orderDetails case [_, _, ''])
'Delivery: Not Started'
else
'Delivery: In Progress',
]; // [Product: Apples, Quantity: 12, Delivery: Not Started]
You can mix different if
operations with an else if
part. For example:
var a = 'apple';
var b = 'orange';
var c = 'mango';
var items = [
0,
if (a == 'apple') 1 else if (a case 'mango') 10,
if (b case 'pear') 2 else if (b == 'mango') 20,
if (c case 'apple') 3 else if (c case 'mango') 30,
4,
]; // [0, 1, 30, 4]
To learn more about the if
conditional, see if
statement. To learn more about the if-case
conditional, see if-case
statement.
For elements
#A for
element iterates and repeatedly evaluates a given inner element, inserting zero or more resulting values.
A for
element has this syntax in a collection:
for (<expression> in <collection>) <result>
for (<initialization_clause>; <condition_clause>; <increment_clause>) <result>
The following examples illustrate various ways that you can use a for
element inside of a collection:
var numbers = [2, 3, 4];
var items = [1, for (var n in numbers) n * n, 7]; // [1, 4, 9, 16, 7]
var items = [1, for (var x = 5; x > 2; x--) x, 7]; // [1, 5, 4, 3, 7]
var items = [1, for (var x = 2; x < 4; x++) x, 7]; // [1, 2, 3, 4, 7]
To learn more about the for
loop, see for
loops.
Nest control flow elements
#You can nest control flow elements within each other. This is a powerful alternative to list comprehensions in other languages.
In the following example, only the even numbers in numbers
are included in items
.
var numbers = [1, 2, 3, 4, 5, 6, 7];
var items = [
0,
for (var n in numbers)
if (n.isEven) n,
8,
]; // [0, 2, 4, 6, 8]
It's common and idiomatic to use a spread on a collection literal immediately inside of an if
or for
element. For example:
var items = [
if (condition) oneThing(),
if (condition) ...[multiple(), things()],
]; // [oneThing, [multiple_a, multiple_b], things]
You can nest all kinds of elements arbitrarily deep. In the following example, if
, for
and spread elements are nested within each other in a collection:
var nestItems = true;
var ys = [1, 2, 3, 4];
var items = [
if (nestItems) ...[
for (var x = 0; x < 3; x++)
for (var y in ys)
if (x < y) x + y * 10,
],
]; // [10, 20, 30, 40, 21, 31, 41, 32, 42]
Unless stated otherwise, the documentation on this site reflects Dart 3.7.3. Page last updated on 2025-05-06. View source or report an issue.