openplanning

Hướng dẫn và ví dụ Dart List

  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>

Trong hầu hết các ngôn ngữ lập trình, mảng là một khái niệm không thể thiếu. Tuy nhiên, ngôn ngữ lập trình Dart không có khái niệm mảng truyền thống, thay vào đó nó sử dụng List (Danh sách) với các tính năng tương tự và bổ xung thêm các tính năng mới.
Sau đây là các đặc điểm của List:
  • Giống như mảng truyền thống, List chứa các phần tử có thứ tự và được đánh chỉ số bắt đầu từ 0.
  • Tuỳ thuộc vào loại List được tạo ra, kích thước của nó là cố định hoặc có khả năng tự động tăng nếu cần thiết.
abstract class List<E> implements EfficientLengthIterable<E>
  • DoubleLinkedQueue
  • IterableBase
  • IterableMixin
  • LinkedList
  • ListQueue
  • Queue
  • Set
  • Runes

2. Constructors

List là một lớp, vì vậy theo suy nghĩ thông thường để tạo một đối tượng bạn cần sử dụng constructor của nó hoặc phương thức nhà máy tĩnh được cung cấp.
Các constructor:
@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?])
Constructor List([int?]) đã lỗi thời (deprecated) và được thay thế bởi cú pháp giống như cách tạo mảng truyền thống:
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});
Ví dụ: Tạo một List có thể tăng kích thước (growable), chứa 5 phần tử, tất cả các phần tử là "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});
Tạo một List rỗng có thể tăng kích thước (growable).
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});
Tạo một đối tượng List chứa tất cả các phần tử của một 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});
Tạo một đối tượng List chứa tất cả các phần tử của một Iterable. Constructor này tương tự như List.of, nhưng nó không có khả năng tự kiểm tra dữ liệu của Iterable đầu vào, vì vậy có thể gây ra lỗi tại thời điểm chạy của chương trình.
Ví dụ:
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});
Trả về một danh sách [length] phần tử với các phần tử được sinh ra theo hàm được chỉ định.
Ví dụ: Tạo một List với 5 phần tử, các phần tử được tạo ra dựa trên chỉ số của nó.
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

Các toán tử của List:
E operator [](int index);
void operator []=(int index, E value);
bool operator ==(Object other);
List<E> operator +(List<E> other);

4. Properties

Các property của List:
void set first(E value);
void set last(E value);
int get length;
set length(int newLength);
Iterable<E> get reversed;

5. Methods

Các phương thức của List:
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();
Trả về một đối tượng Map<int,E> không thể sửa đổi (unmodifiable), với các giá trị 0, 1, 2.. là các khoá và các phần tử của danh sách là các giá trị.
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>();
Trả về một dạng xem của List<E> này dưới dạng List<R>.
Ví dụ:
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);
Một phương thức tĩnh trả về một dạng xem của một List<S> được chỉ định, dưới dạng List<R>.
Ví dụ:
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])
Thay thế các phần tử từ chỉ số [at] của một List bởi các phần tử từ chỉ số [start] đến [end-1] của một Iterable.
Phương thức này có thể ném ra RangeError nếu:
end - start + at > target.length
Ví dụ:
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]);
Thay thế tất cả các phần tử từ chỉ số [start] tới [end-1] bởi [fillValue].
Ví dụ:
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]);
Trả về chỉ số của phần tử đầu tiên vượt qua kiểm tra được chỉ định.
Ví dụ:
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);
Chèn tất cả các phần tử của một Iterable vào List này tại chỉ số [index].
Ví dụ:
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));
Loại bỏ tất cả các phần tử vượt qua kiểm tra được chỉ định.
Ví dụ:
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);
Thay thế các phần tử từ chỉ số [start] tới [end-1] của List này bởi các phần tử của Iterable được chỉ định.
Ví dụ:
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));
Loại bỏ tất cả các phần tử không vượt qua một kiểm tra được chỉ định.
Ví dụ:
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);
Thay thế các phần tử từ chỉ số [index] của List này bởi các phần tử của một Iterable được chỉ định.
Phương thức này sẽ ném ra RangeError nếu:
iterable.length + index > thisList.length
Ví dụ:
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]);
Xáo trộn các phần tử của danh sách này một cách ngẫu nhiên.
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);
Thay thế các phần tử từ chỉ số [at] của một List bởi các phần tử của một Iterable.
Phương thức này sẽ ném ra RangeError nếu:
source.length + at > target.length
Ví dụ:
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]