o7planning

Dart List Tutorial with Examples

  1. List<E>
  2. Constructors
  3. Operators
  4. Properties
  5. Methods
  6. asMap()
  7. cast<R>()
  8. castFrom<S, T>(..)
  9. copyRange<T>(..)
  10. fillRange(..)
  11. indexWhere(..)
  12. insertAll(..)
  13. removeWhere(..)
  14. replaceRange(..)
  15. retainWhere(..)
  16. setAll(..)
  17. shuffle([Random? random])
  18. writeIterable<T>(..)

1. List<E>

In most programming languages, array is an indispensable concept. However, the Dart programming language does not have the traditional array concept. Instead, it uses List with similar features and added new a ones.
Below are the characteristics of List:
  • Like traditional arrays, List contains ordered elements and is indexed starting at 0.
  • Depending on the type of List created, its size is fixed or can be automatically increased if necessary.
abstract class List<E> implements EfficientLengthIterable<E>
  • DoubleLinkedQueue
  • IterableBase
  • IterableMixin
  • LinkedList
  • ListQueue
  • Queue
  • Set
  • Runes

2. Constructors

List is a class. By common sense, to create an object you need to use its constructor or the provided static factory method.
Constructors:
@Deprecated("Use a list literal, [], or the List.filled constructor instead")
external factory List([int? length]);

external factory List.filled(int length, E fill, {bool growable = false});
@Since("2.9")
external factory List.empty({bool growable = false});
external factory List.from(Iterable elements, {bool growable = true});
external factory List.of(Iterable<E> elements, {bool growable = true});
external factory List.generate(int length, E generator(int index), {bool growable = true});
external factory List.unmodifiable(Iterable elements);
List([int?])
The List([int?]) constructor is deprecated and has been replaced by the same syntax as traditional array creation:
list_ex1.dart
var foo1 = List<String>();  // Deprecated (error)
var bar1 = List<String>(n); // Deprecated (error)
var baz1 = List<String>(0); // Deprecated (error)

List<int> foo2 = List<int>();  // Deprecated (error)
List<int> bar2 = List<int>(n); // Deprecated (error)
List<int> baz2 = List<int>(0); // Deprecated (error)

var foo3 = []; // OK
var bar3 = ["One", "Two"]; // OK

var foo4 = <String>[]; // OK
var bar4 = <String>["One", "Two"]; // OK

List<String> foo5 = []; // OK
List<String> bar6 = ["One", "Two"]; // OK

List<String> foo7 = <String>[]; // OK
List<String> bar7 = <String>["One", "Two"]; // OK
List.filled
external factory List.filled(int length, E fill, {bool growable = false});
Example: Create a growable List, containing 5 elements, all elements are "Foo":
var list1 = List<String>.filled(5, 'Foo', growable: true);
var list2 = List.filled(5, 'Foo', growable: true);
List<String> list3 = List.filled(5, 'Foo', growable: true);
List.empty
@Since("2.9")
external factory List.empty({bool growable = false});
Create an empty List that can grow in size.
var list1 = List<String>.empty(growable: true);  
var list2 = List.empty(growable: true);  
List<String> list3 = List.empty(growable: true);

// Same as:
var list4 = <String>[];
List<String> list5 = [];
List.of
external factory List.of(Iterable<E> elements, {bool growable = true});
Creates a List object containing all the elements of an Iterable.
list_of_ex1.dart
import 'dart:collection';

void main() {
  // A collection containing non-duplicate elements
  var iterator = Set<String>.identity();
  iterator.add('Tom');
  iterator.add('Jerry');
  iterator.add('Donald');
  var list = List<String>.of(iterator, growable: true);
  print(list); // [Tom, Jerry, Donald]
}
List.from
external factory List.from(Iterable elements, {bool growable = true});
Create a List object containing all the elements of an Iterable. This constructor is similar to List.of, but it does not have the ability to check the input Iterable's data by itself, so it can cause errors at runtime of the program.
Example:
list_from_ex1.dart
void main() {
  // A collection containing non-duplicate elements
  var iterator = Set<dynamic>.identity(); // Any data type
  iterator.add('Tom');    // String data type
  iterator.add('Jerry');  // String data type
  iterator.add(1000);     // int data type

  var list = List<String>.from(iterator, growable: true); // Compile OK!! but Error at runtime.
  print(list);  
}
Output:
Unhandled exception:
type 'int' is not a subtype of type 'String'
#0      new List.from (dart:core-patch/array_patch.dart:40:5)
#1      main
bin/list_from_ex1.dart:10
#2      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:283:19)
#3      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)
List.generate
external factory List.generate(int length, E generator(int index), {bool growable = true});
Returns a list of [length] elements with the elements generated by the specified function.
Example: Create a List with 5 elements, the elements are generated based on their indexes.
list_generate_ex1.dart
import 'dart:collection';
void main() {  
  // Create a Clousure (Function)
  var generator = (index)  {
     return 'Element $index';
  };
  var list = List<String>.generate(5, generator, growable: true );  
  print(list);  // [Element 0, Element 1, Element 2, Element 3, Element 4] 
}
List.unmodifiable
external factory List.unmodifiable(Iterable elements);

3. Operators

List operators:
E operator [](int index);
void operator []=(int index, E value);
bool operator ==(Object other);
List<E> operator +(List<E> other);

4. Properties

List properties:
void set first(E value);
void set last(E value);
int get length;
set length(int newLength);
Iterable<E> get reversed;

5. Methods

List methods:
static List<T> castFrom<S, T>(List<S> source) => CastList<S, T>(source);

static void copyRange<T>(List<T> target, int at, List<T> source, [int? start, int? end])  
    
static void writeIterable<T>(List<T> target, int at, Iterable<T> source);  

void add(E value);
void addAll(Iterable<E> iterable);

List<R> cast<R>();

void sort([int compare(E a, E b)?]);
void shuffle([Random? random]);

int indexOf(E element, [int start = 0]);
int indexWhere(bool test(E element), [int start = 0]);
int lastIndexWhere(bool test(E element), [int? start]);
int lastIndexOf(E element, [int? start]);

void clear();

void insert(int index, E element);
void insertAll(int index, Iterable<E> iterable);
void setAll(int index, Iterable<E> iterable);
bool remove(Object? value);
E removeAt(int index);
E removeLast();
void removeWhere(bool test(E element));
void retainWhere(bool test(E element));

List<E> sublist(int start, [int? end]);
Iterable<E> getRange(int start, int end);
void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]);
void removeRange(int start, int end);
void fillRange(int start, int end, [E? fillValue]);
void replaceRange(int start, int end, Iterable<E> replacements);
Map<int, E> asMap();

6. asMap()

Map<int, E> asMap();
Returns an unmodifiable Map<int,E> object, with the values 0, 1, 2.. as keys and the elements of the list as values.
list_asMap_ex1.dart
void main() {
  var list = <String>['Tom', 'Jerry', 'Donald'];
 
  Map<int,String> map = list.asMap();
  for(var idx in map.keys) {
    print('idx: $idx --> ${map[idx]}');
  }
}
Output:
idx: 0 --> Tom
idx: 1 --> Jerry
idx: 2 --> Donald

7. cast<R>()

List<R> cast<R>();
Returns a view of this List<E> as a List<R>.
Example:
list_cast_ex1.dart
class Person {}
class Employee extends Person {
  String name;
  Employee(this.name);
}
void main() {
  var p1 = Employee('Jennifer');
  var p2 = Employee('James');
  var p3 = Employee('John');

  var list = <Person>[p1, p2, p3]; // List<Person>
  var empList = list.cast<Employee>(); // List<Employee>

  for (var emp in empList) {
    print(emp.name);
  }
}
Output:
Jennifer
James
John

8. castFrom<S, T>(..)

static List<T> castFrom<S, T>(List<S> source) => CastList<S, T>(source);
A static method that returns a view of a specified List<S>, as a List<R>.
Example:
list_castFrom_ex1.dart
class Person {}
class Employee extends Person {
  String name;
  Employee(this.name);
}
void main() {
  var p1 = Employee('Jennifer');
  var p2 = Employee('James');
  var p3 = Employee('John');
  var personList = <Person>[p1, p2, p3]; // List<Person>
  var empList = List.castFrom<Person, Employee>(personList); // List<Employee>

  for (var emp in empList) {
    print(emp.name);
  }
}
Output:
Jennifer
James
John

9. copyRange<T>(..)

static void copyRange<T>(List<T> target, int at, List<T> source, [int? start, int? end])
Replace elements from index [at] of a List by elements from index [start] to [end-1] of an Iterable.
This method may throw a RangeError if:
end - start + at > target.length
Example:
list_copyRange_ex1.dart
void main() {
  var sourceList = <String>['Zero', 'One', 'Two', 'Three'];
  var targetList = <String>['0', '1', '2', '3', '4', '5'];

  List.copyRange(targetList, 2, sourceList, 1, 3);
  print(targetList);
}
Output:
[0, 1, One, Two, 4, 5]

10. fillRange(..)

void fillRange(int start, int end, [E? fillValue]);
Replace all elements from index [start] to [end-1] by [fillValue].
Example:
list_fillRange_ex1.dart
void main() {
  var flowers = <String>['Rose', 'Lily', 'Sunflower',  'Lotus', 'Water Lily', 'Marigold', 'Lavender'];
  print(flowers);
  print(' -- fillRange from index 2 to 5 -- ');  
  flowers.fillRange(2, 5, 'A');
  print(flowers);
}
Output:
[Rose, Lily, Sunflower, Lotus, Water Lily, Marigold, Lavender]
 -- fillRange from index 2 to 5 --
[Rose, Lily, A, A, A, Marigold, Lavender]

11. indexWhere(..)

int indexWhere(bool test(E element), [int start = 0]);
Returns the index of the first element that passes the specified test.
Example:
list_indexWhere_ex1.dart
void main() {
  var flowers = <String>['Rose', 'Lily', 'Sunflower',  'Lotus', 'Water Lily', 'Marigold', 'Lavender'];

  var test = (String element) => element.contains('L'); // A Closure.

  var index = flowers.indexWhere((element) => element.contains('L'), 2);
  print('index found: $index --> ${flowers[index]}'); // 3 --> Lotus
}
Output:
index found: 3 --> Lotus

12. insertAll(..)

void insertAll(int index, Iterable<E> iterable);
Insert all elements of an Iterable into this List at [index] index.
Example:
list_insertAll_ex1.dart
void main() {
  var flowers = <String>['Rose', 'Lily', 'Sunflower',  'Lotus', 'Snowdrop', 'Marigold', 'Lavender'];
  print(flowers);

  Iterable<String> iterable = ['A', 'B', 'C'];
  flowers.insertAll(2, iterable);
  print(' --- After insertAll --- ');
  print(flowers);
}
Output:
[Rose, Lily, Sunflower, Lotus, Snowdrop, Marigold, Lavender]
 --- After insertAll ---
[Rose, Lily, A, B, C, Sunflower, Lotus, Snowdrop, Marigold, Lavender]

13. removeWhere(..)

void removeWhere(bool test(E element));
Removes all elements that pass the specified test.
Example:
list_removeWhere_ex1.dart
void main() {
  var flowers = <String>['Rose', 'Lily', 'Sunflower',  'Lotus', 'Water Lily', 'Marigold', 'Lavender'];
  print(flowers);

  var test = (String element) {  // A Closure.
     return element.contains('L') || element.contains('R');
  };
  flowers.removeWhere(test);
  print(' -- after removing -- ');
  print(flowers);
}
Output:
[Rose, Lily, Sunflower, Lotus, Water Lily, Marigold, Lavender]
 -- after removing --
[Sunflower, Marigold]

14. replaceRange(..)

void replaceRange(int start, int end, Iterable<E> replacements);
Replaces the elements from the index [start] to [end-1] of this List by the elements of the specified Iterable.
Example:
list_replaceRange_ex1.dart
void main() {
  var flowers = <String>['Rose', 'Lily', 'Sunflower',  'Lotus', 'Water Lily', 'Marigold', 'Lavender'];
  print(flowers);
  print(' -- Replace elements from index 2 to 5 -- ');
  var iterable = ['A', 'B']; // Note: List is subclass of Iterable.

  flowers.replaceRange(2, 5, iterable);
  print(flowers); // [Rose, Lily, A, B, Marigold, Lavender]
}
Output:
[Rose, Lily, Sunflower, Lotus, Water Lily, Marigold, Lavender]
 -- Replace elements from index 2 to 5 --
[Rose, Lily, A, B, Marigold, Lavender]
  • Dart Iterable

15. retainWhere(..)

void retainWhere(bool test(E element));
Removes all elements that do not pass a specified test.
Example:
list_retainWhere_ex1.dart
void main() {
  var flowers = <String>['Rose', 'Lily', 'Sunflower',  'Lotus', 'Snowdrop', 'Marigold', 'Lavender'];
  print(flowers);

  var test = (String element)  => element.startsWith('S'); // A Clousure.
  flowers.retainWhere(test);
  print(flowers);
}
Output:
[Rose, Lily, Sunflower, Lotus, Snowdrop, Marigold, Lavender]
 -- fillRange from index 2 to 5 --
[Sunflower, Snowdrop]

16. setAll(..)

void setAll(int index, Iterable<E> iterable);
Replaces elements from the [index] index of this List by the elements of a specified Iterable.
This method will throw a RangeError if:
iterable.length + index > thisList.length
Example:
list_setAll_ex1.dart
void main() {
  var flowers = <String>['Rose', 'Lily', 'Sunflower',  'Lotus', 'Snowdrop', 'Marigold', 'Lavender'];
  print(flowers);

  Iterable<String> iterable = ['A', 'B', 'C'];
  flowers.setAll(2, iterable);
  print(' --- After setAll --- ');
  print(flowers);
}
Output:
[Rose, Lily, Sunflower, Lotus, Snowdrop, Marigold, Lavender]
 --- After setAll ---
[Rose, Lily, A, B, C, Marigold, Lavender]

17. shuffle([Random? random])

void shuffle([Random? random]);
Shuffles the elements of this list randomly.
list_shuffle_ex1.dart
import 'dart:math';
void main() {
  var list = <int>[1, 2, 3, 4, 5, 6,7];
  list.shuffle(); //
  print(list);

  var random = Random(5); // seed = 5
  list.shuffle(random);
  print(list);
}
Output:
[4, 2, 5, 6, 7, 3, 1]
[3, 7, 6, 2, 5, 4, 1]

18. writeIterable<T>(..)

static void writeIterable<T>(List<T> target, int at, Iterable<T> source);
Replace the elements from the [at] index of a List by the elements of an Iterable.
This method will throw a RangeError if:
source.length + at > target.length
Example:
list_writeIterable_ex1.dart
void main() {
  // Note: List is subclass of Iterable.
  Iterable<String> sourceIterable = <String>['Zero', 'One', 'Two', 'Three'];  
  var targetList = <String>['0', '1', '2', '3', '4', '5', '6', '7'];

  List.writeIterable(targetList, 2, sourceIterable);
  print(targetList);
}
Output:
[0, 1, Zero, One, Two, Three, 6, 7]