js-数组:https://www.yuque.com/zhuchaoyang/wrif6k/oe5z47
List-API-docs:https://api.dart.dev/stable/2.10.3/dart-core/List-class.html

几乎每种编程语言中最常见的集合可能是 array 或有序的对象集合。 在 Dart 中的 Array 就是 List 对象, 通常称之为 List

Dart 中的 List 字面量非常像 JavaScript 中的 array 字面量。
List 类型包含了很多 List 的操作函数。 更多信息参考 泛型集合.

定义常数的List

在 List 字面量之前添加 const 关键字,可以定义 List 类型的编译时常量:

  1. var s1 = const [1, 2, 3];
  2. s1.add(4); //报错
  3. s1[1] = 1; //报错

声明方式

下面为什么只有 List() ,而不是使用 new List()。 因为在 Dart 2 中,new 关键字是可选的。 有关更多信息,参考 构造函数的使用

  1. // 声明方式1:字面量
  2. var s1 = [1, 2, 3]; //初始就赋值了,限定了长度,限定了类型,只能是int
  3. var s11 = <int>[1, 2, 3];
  4. List s12 = <int>[1, 2, 3];
  5. List<int> s13 = [1, 2, 3];
  6. var s4 = [1, 'a', true]; //初始就赋值了,限定了长度,未限定类型,任意位置可用任意类型替换
  7. print(s1); //[1, 2, 3]
  8. print(s1 is List); //true
  9. // 声明方式2:构造函数
  10. var s1 = List(); //不限定长度,不限定类型,可添加任意类型的数据
  11. List s2 = List(); // 不限定长度,不限定类型,可添加任意类型的数据
  12. List s3 = List(2); //限定了长度为2,越界会报错,不限定类型,可添加任意类型的数据
  13. List s4 = List<int>(); //不限定长度,限定了类型,只能是int
  14. print(s3); //[null, null]

类型推断

Dart建议List里面最好放同一种数据类型。有关更多信息,请阅读 类型推断。

无指定泛型

字面量方式,有默认推断
  1. // 默认推断类型为 int,如果添加元素为非int类型,就会报错。
  2. var s1 = [1];
  3. s1.add(2);
  4. // s1.add('a'); //报错
  5. // 默认推断类型为 String
  6. var s2 = ['a'];
  7. s2.add('b');
  8. // s2.add(1); //报错

字面量方式,无默认推断。可添加任意类型。
  1. var s3 = [1, 'a'];
  2. s3.add({});
  3. print(s3); //[1, 'a', {}]
  4. var s4 = [];
  5. s4.add(1);
  6. s4.add('a');
  7. print(s4); //[1, 'a']

构造函数方式,无默认推断。可添加任意类型。
  1. var s5 = List();
  2. s5.add(1);
  3. s5.add('a');
  4. print(s5); //[1, 'a']

指定泛型

字面量方式
  1. // 指定类型为 int
  2. var s1 = <int>[1, 2];
  3. // List s1 = <int>[1, 2];
  4. // List<int> s1 = [1, 2];
  5. s1.add(3);
  6. s1.add('a'); //报错

构造函数方式
  1. // 指定类型为 int
  2. var s1 = List<int>(); //即:var s1 = new List<int>(); Dart2之后,new关键字可省略
  3. // List s1 = List<int>();
  4. // List<int> s1 = List();
  5. s1.add(3);
  6. s1.add('a'); //报错

constructors

filled

https://api.dart.dev/stable/2.10.3/dart-core/List/List.filled.html
使用给定值,填充一个数组。

  1. var s1 = List.filled(3, 1);
  2. print(s1); //[1, 1, 1]
  3. //如果填充的类型为对象,那么被赋值的是同一个内存地址的对象,而不是深拷贝对象。
  4. var s1 = List.filled(3, []);
  5. s1[0].add(1);
  6. print(s1); //[[1], [1], [1]]
  7. //You can use List.generate to create a list with a new object at each position.
  8. var s1 = List.generate(3, (index) => []);
  9. s1[0].add(1);
  10. print(s1); //[[1], [], []]

growable 创建的数组是否可增长,默认为false

  1. var s1 = List.filled(3, 1, growable: false);
  2. print(s1); //[1, 1, 1]
  3. s1.add(2); //报错:Cannot add to a fixed-length list
  4. var s1 = List.filled(3, 1, growable: true);
  5. print(s1); //[1, 1, 1]
  6. s1.add(2);
  7. print(s1); //[1, 1, 1, 2]

generate

Generates a list of values.

Creates a list with length positions and fills it with values created by calling generator for each index in the range 0 .. length - 1 in increasing order.

  1. List<int>.generate(3, (int index) => index * index); // [0, 1, 4]
  1. var s2 = List.generate(3, (int index) => index * index);
  2. print(s2); //[0, 1, 4]
  3. var s3 = List.generate(3, (index) {
  4. return index;
  5. });
  6. print(s3); //[0, 1, 2]

属性

length

Lists 的下标索引从 0 开始,第一个元素的索引是 0。 list.length - 1 是最后一个元素的索引。 访问 List 的长度和元素与 JavaScript 中的用法一样:

  1. var s1 = [1, 2, 3];
  2. print(s1.length); //3
  3. print(s1[0]); //1 获取指定索引的元素值
  4. s1[0] = 5; //修改指定索引的元素值

first、last 返回首位、末位元素

  1. var s1 = [1, 2, 3, 4];
  2. print(s1.first); //1
  3. print(s1.last); //4

isEmpty、isNotEmpty 是否为空、不为空

  1. var s1 = [];
  2. print(s1.isEmpty); //true
  3. print(s1.isNotEmpty); //false

single

如果数组中有且只有一个元素,返回该元素。
如果数组中没有元素,或者有至少2个元素,就会报错。

  1. var s1 = [];
  2. var s2 = [1];
  3. var s3 = [1, 2];
  4. // print(s1.single); //报错
  5. print(s2.single); //1
  6. print(s3.single); //报错

reversed 倒置

返回一个List的倒序排列的 Iterable原数组不变

  1. var s1 = [1, 2, 3];
  2. print(s1.reversed); //(3, 2, 1)

hashCode

返回此对象的哈希码。

  1. var s1 = [1, 2, 3];
  2. print(s1.hashCode); //480963117

Iterable

方法

转换

toString

  1. var s1 = [1, 2, 3];
  2. print(s1.toString()); //"[3, 2, 1]"

toList

Creates a List containing the elements of this Iterable.
The elements are in iteration order. The list is fixed-length if growable is false.

  1. var s1 = [1, 2, 3];
  2. var s2 = s1.reversed;
  3. print(s2); //Iterable (3, 2, 1)
  4. print(s2.toList()); //[3, 2, 1]

toSet

将List转为Set,并去除后面重复的元素。原数组不变

  1. var s1 = [1, 2, 3, 2, 1];
  2. print(s1.toSet()); //Set {1, 2, 3}

应用:list去重
  1. var s1 = [1, 2, 3, 1, 5, 2];
  2. print(s1.toSet().toList()); //[1, 2, 3, 5]
  3. var s2 = Set();
  4. s2.addAll(s1);
  5. print(s2); //[1, 2, 3, 5]

asMap

将list转为map。原数组不变

  1. var s1 = ['a', 'b'];
  2. print(s1.asMap()); //Map {0: 'a', 1: 'b'}

join 连接

把数组转换为字符串,可以设置每一项之间的连接符,返回转换的字符串。原数组不变

  1. var s1 = [1, 2, 3];
  2. print(s1.join()); //"123" 注意:不传参数的时候,js默认为逗号隔开;dart默认就是没有分隔符
  3. print(s1.join(',')); //"1,2,3"

增删改

add、addAll 添加元素

add(element) 添加一个元素到 List 末尾。
addAll(List) 添加一个 List 到 List 末尾。

  1. // add(element) 添加一个元素到 List 末尾
  2. var s1 = [1, 2];
  3. s1.add(3);
  4. print(s1); //[1, 2, 3]
  5. // addAll(List) 添加一个 List 到 List 末尾。
  6. var s2 = [1, 2];
  7. s2.addAll([4, 5]);
  8. print(s2); //[1, 2, 4, 5]

insert、insertAll 指定插入

insert(index, element) 在指定的index处插入元素,其余顺延。
insertAll(index, List) 在指定的index处插入 List,其余顺延。(合并两个 List )

  1. // insert(index, elememt) 在指定的index处插入元素
  2. var s3 = [0, 1, 2, 3, 4, 5];
  3. s3.insert(1, 4);
  4. print(s3); //[0, 4, 1, 2, 3, 4, 5]
  5. //insert(index, List) 在指定的index处插入 List
  6. var s4 = [0, 1, 2, 3, 4, 5];
  7. s4.insertAll(1, [10, 20]);
  8. print(s4); //[0, 10, 20, 1, 2, 3, 4, 5]

remove、removeAt、removeLast、removeRange、removeWhere 删除元素

remove(obj) 删除具体的元素。如果有找到,返回 true 。
removeAt(index) 删除指定索引的元素,返回删除的元素。
removeLast() 删除末尾元素,返回删除的元素。
removeRange(start, end) 删除指定范围内的元素,含头不含尾。
removeWhere((item) => item > 2) 根据参数(函数)的返回条件,进行筛选。

  1. // remove(element) 删除具体的元素
  2. List s1 = [1, 3, 5, 7];
  3. print(s1.remove(3)); //true
  4. print(s1); //[1, 5, 7]
  5. // removeAt(index) 删除指定索引的元素
  6. List s2 = [1, 3, 5, 7];
  7. print(s2.removeAt(1)); //3
  8. print(s2); //[1, 5, 7]
  9. // removeLast() 删除末尾元素
  10. List s3 = [1, 3, 5, 7];
  11. print(s3.removeLast()); //7
  12. print(s3); //[1, 3, 5]
  13. // removeRange(start, end) 删除指定范围内的元素,含头不含尾。
  14. List s4 = [1, 3, 5, 7];
  15. s4.removeRange(0, 2);
  16. print(s4); //[5, 7]
  17. // removeWhere((item) => item > 2) 根据参数(函数)的返回条件,进行筛选。
  18. List s5 = [1, 3, 5, 7];
  19. s5.removeWhere((item) => item > 3);
  20. // 等同于
  21. // s5.removeWhere((item) {
  22. // return item > 3;
  23. // });
  24. print(s5); //[1, 3]

clear() 清除所有元素

  1. var s1 = [1, 2, 3, 4];
  2. s1.clear();
  3. print(s1); //[]

retainWhere 保留

按条件保留,无返回。

  1. var s1 = [1, 2, 3, 4];
  2. s1.retainWhere((item) => item > 2);
  3. print(s1); //[3, 4]

setRange、replaceRange、fillRange 修改元素

setRange(start, end, List) 范围修改,含头不含尾,无返回。
replaceRange(start, end, List) 范围替换,含头不含尾,无返回(类似js的 splice)。
fillRange(start, end, element) 用指定的值替换范围内的值,含头不含尾,无返回。

  1. // setRange(start, end, List) 范围修改
  2. List s1 = [0, 1, 2, 3, 4, 5];
  3. List s2 = [11, 13, 15, 17, 19];
  4. // 从s2取出 0 1 2 位置的值,修改s1对应 0 1 2 位置的值
  5. s1.setRange(0, 3, s2); //[11, 13, 15, 3, 4, 5]
  6. // s1.setRange(3, 3, s2); //[0, 1, 2, 3, 4, 5] start和end相同,则不变。
  7. // s1.setRange(3, 10, s2); //start和end任何一个超出s1 s2的角标 则报错。
  8. print(s1);
  1. // replaceRange(start, end, List) 范围替换
  2. List s1 = [0, 1, 2, 3, 4, 5];
  3. List s2 = [11, 13, 15, 17, 19];
  4. s1.replaceRange(0, 3, s2); //[11, 13, 15, 17, 19, 3, 4, 5]
  5. // s1.replaceRange(3, 3, s2); //[0, 1, 2, 11, 13, 15, 17, 19, 3, 4, 5]
  6. // s1.replaceRange(3, 10, s2); //start和end任何一个超出s1 s2的角标,则报错。
  7. print(s1);
  1. // fillRange(start, end, element) 用指定的值替换范围内的值
  2. List s1 = [0, 1, 2, 3, 4, 5];
  3. List s2 = [99];
  4. s1.fillRange(0, 3, s2); //[[99], [99], [99], 3, 4, 5]
  5. // s1.fillRange(3, 3, s2); //[0, 1, 2, 3, 4, 5]
  6. // s1.fillRange(3, 10, s2); //start和end任何一个超出s1 s2的角标,则报错。
  7. print(s1);

setAll

setAll(index, List) 从index开始,使用List内的元素逐个替换本 List 中的元素。

  1. var s1 = [0, 1, 2, 3, 4, 5];
  2. s1.setAll(2, [10, 11]);
  3. print(s1); //[0, 1, 10, 11, 4, 5]

查找、获取

elementAt 获取指定索引的元素

elementAt(index) 获取指定索引位置的元素。

  1. var s1 = [1, 2, 3, 4];
  2. print(s1.elementAt(1)); //2
  3. print(s1[1]); //2

indexOf、lastIndexOf

往前、后查找当前值在数组中第一次出现的位置索引。原数组不变返回**:索引,没有找到返回 -1

  • 第一个参数:要查找的值
  • 第二个参数:开始查找的索引,默认从索引 0 开始查找。indexOf、lastIndexOf 会从索引位置开始往前、后查找。 ```dart var s1 = [1, 2, 3, 4, 3, 2]; print(s1.indexOf(3)); //2 print(s1.indexOf(3, 3)); //4

print(s1.lastIndexOf(3)); //4 print(s1.lastIndexOf(3, 1)); //-1

  1. <a name="uYxv4"></a>
  2. ### contains 是否含有指定元素
  3. `contains(obj)` 返回布尔值,表示是否找到了指定元素
  4. ```dart
  5. var s1 = [1, 2, 3, 4];
  6. print(s1.contains(2)); //true

firstWhere、lastWhere

firstWhere((e)=>(bool)) 返回第一个满足条件的元素(不是元素的index)
lastWhere((e)=>(bool)) 从后往前找,返回第一个满足条件的元素的值(不是index)

  1. var s1 = [1, 3, 5, 7];
  2. print(s1.firstWhere((item) => item > 2)); //3
  3. print(s1.lastWhere((item) => item > 2)); //7
  4. // 返回满足条件的第一个元素,不满足 报错
  5. // print(s1.firstWhere((item) => item > 8)); //不满足,报错
  6. // 返回满足条件的第一个元素,不满足 返回orElse方法的返回值
  7. print(s1.firstWhere((item) => item > 8, orElse: () => (10))); //10

indexWhere、lastIndexWhere

indexWhere((e)=>(bool)) 返回第一个满足条件的元素的index
lastIndexWhere((e)=>(bool)) 从后向前找 返回第一个满足条件的元素的index

  1. var s1 = [1, 3, 5, 7];
  2. print(s1.indexWhere((item) => item > 2)); //1
  3. print(s1.lastIndexWhere((index) => index > 2)); //3
  4. //返回第一个满足条件的元素的index 不存在则返回-1
  5. print(s1.indexWhere((item) => item > 10)); //-1
  6. //返回第一个满足条件的元素的index,从index为2开始寻找
  7. print(s1.indexWhere((item) => item > 3, 2)); //2
  8. print(s1.indexWhere((item) => item > 10, 2)); //-1

sublist、getRange 获取指定范围内元素

sublist(start,[end]) 从指定index 截取list,返回 List。原数组不变
getRange(start,end) 从list中截取start-end范围内的数据,返回 Iterable。原数组不变

  1. // sublist(start, [end]) end可选
  2. var s1 = [0, 1, 2, 3, 4, 5];
  3. print(s1.sublist(1)); //[1, 2, 3, 4, 5]
  4. print(s1.sublist(1, 3)); //[1, 2]
  5. // print(s1.sublist(-1)); //报错
  6. // getRange(start, end)
  7. var s2 = [0, 1, 2, 3, 4, 5];
  8. // print(s2.getRange(1)); //报错
  9. print(s2.getRange(1, 3)); //Iterable (1, 2)

take、takeWhile 获取元素

take(count) 从0开始取count个元素,并以 Iterable 形式返回。原数组不变
skipWhile((item) => (bool)) 从0开始取,直至第一个不符合函数的元素,将其前面的元素以 Iterable 形式返回。原数组不变

  1. // take(count)
  2. var s1 = [1, 2, 3, 4, 5];
  3. print(s1.take(2)); //Iterable (1, 2)
  4. // takeWhere((item) => (bool))
  5. var s2 = [1, 2, 3, 4, 5];
  6. print(s2.takeWhile((item) => (item < 3))); //Iterable (1, 2)

skip、skipWhile 反选元素

skip(count) 越过count个元素后,然后将其之后的元素以 Iterable 形式返回。原数组不变
skipWhile((item) => (bool)) 找到第一个不符合条件的元素,然后将其及其之后的元素以 Iterable 形式返回。原数组不变

  1. // skip(count)
  2. var s1 = [1, 2, 3, 4, 5];
  3. print(s1.skip(2)); //Iterable (3, 4, 5)
  4. // skipWhere((item) => (bool))
  5. var s2 = [1, 2, 3, 4, 5];
  6. print(s2.skipWhile((item) => (item < 3))); //Iterable (3, 4, 5)

排序

sort 自定义排序

对数组元素进行排序。返回排序后的数组。原数组改变

不传参数
将按字母顺序对数组中的元素进行排序,说得更精确点,是按照字符Uniode编码的顺序进行排序。要实现这一点,首先应把数组的元素都转换成字符串(toString() 方法),以便进行比较。

  1. var a1 = ['George', 'John', 'Thomas', 'James', 'Adrew', 'Martin'];
  2. a1.sort();
  3. print(a1); //[Adrew, George, James, John, Martin, Thomas]
  4. //js:基于 sort 本身的排序方法,数字不会按照我们预想的排序
  5. var a2 = [1, 19, 2, 24];
  6. a2.sort();
  7. print(a2); //[1, 2, 19, 24]
  8. //dart没有这个问题
  9. var a2 = [1, 19, 2, 24];
  10. a2.sort();
  11. print(a2); //[1, 2, 19, 24]

传递参数(比较函数)
该函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。

以升序为例,比较函数应该具有两个参数 a 和 b,其返回值如下:

  • 若 a 小于 b,在排序后的数组中 a 应该出现在 b 之前,则返回一个小于 0 的值。
  • 若 a 等于 b,则返回 0。
  • 若 a 大于 b,在排序后的数组中 a 应该出现在 b 之后,则返回一个大于 0 的值。
  1. var s1 = [1, 19, 2, 24];
  2. // 升序
  3. s1.sort((a, b) => a - b);
  4. // s1.sort((a, b) => a < b ? -1 : 1);
  5. print(s1); //[1, 2, 19, 24]
  6. // 降序
  7. s1.sort((a, b) => b - a);
  8. // s1.sort((a, b) => a < b ? 1 : -1);
  9. print(s1); //[24, 19, 2, 1]

shuffle 随机重排数组

List内元素,重新随机排列。原数组改变

  1. var s1 = [1, 2, 3, 4, 5];
  2. s1.shuffle();
  3. print(s1); //[4, 5, 2, 1, 3]

数组的遍历

for 循环

  1. var s1 = [1, 2, 3];
  2. for (var i = 0; i < s1.length; i++) {
  3. print(s1[i]); //依次输出 1 2 3
  4. }

for…in

  1. var s1 = [1, 2, 3];
  2. for (var v in s1) {
  3. print(v); //依次输出 1 2 3
  4. }

forEach

用于调用数组的每个元素,并将元素传递给回调函数。

  1. var s1 = [1, 2, 3];
  2. s1.forEach((item) {
  3. //遍历每个元素 此时不可add或remove 否则报错 但可以修改元素值,
  4. s1[0] = 10;
  5. });
  6. print(s1); //[10, 2, 3]

map

遍历现有List的每个元素,并做处理,返回一个新的Iterable。原数组不变

  1. var s1 = [0, 1, 2, 3, 4, 5];
  2. var s2 = s1.map((item) => item * 2);
  3. print(s2); //Iterable (0, 2, 4, 6, 8, 10)
  4. print(s1); //List [0, 1, 2, 3, 4, 5]
  5. Iterable<bool> s3 = s1.map((item) => item > 2);
  6. print(s3); //Iterable (false, false, false, true, true, true)

any、every

  • any 用于检测数组中是否有任意一个元素满足指定条件。不改变原数组
  • every 用于检测数组中所有元素是否都符合指定条件。不改变原数组
    ```dart var s1 = [1, 2, 3]; print(s1.any((item) => item > 2)); //true print(s1.any((item) => item > 4)); //false

print(s1.every((item) => item > 0)); //true print(s1.every((item) => item > 2)); //false

  1. <a name="0JS6D"></a>
  2. ### where、whereType、singleWhere 筛选元素
  3. `where((e)=>(bool)` 根据指定参数函数筛选每个元素,符合条件的元素组成一个新的Iterable集合。**原数组不变**<br />`whereType()` 从无指定泛型的List中,筛选出指定类型的数据,组成一个新的Iterable集合。**原数组不变**<br />`singleWhere((e)=>(bool>)` 找到那唯一满足条件的元素。**原数组不变**
  4. ```dart
  5. // where((e) => (bool)) 根据条件,筛选元素
  6. var s1 = [1, 2, 3, 4, 5];
  7. print(s1.where((item) => item > 2)); //Iterable (3, 4, 5)
  8. // whereType() 根据数据类型,筛选元素
  9. List s2 = [3, 4, "a", true, "b", 5, false];
  10. Iterable<int> s21 = s2.whereType(); //筛选出int类型的元素
  11. print(s21); //Iterable (3, 4, 5)
  12. //singleWhere 根据条件,筛选唯一元素
  13. var s3 = [1, 2, 3, 4, 5];
  14. print(s3.singleWhere((item) => item == 2)); //2
  15. // 找到那唯一满足条件的元素,如果没有满足条件的元素或有多个元素满足条件,
  16. // 就返回orElse方法的返回值,如果没有传入orElse则报错。
  17. print(s3.singleWhere((item) => item > 10)); //报错
  18. print(s3.singleWhere((item) => item > 10, orElse: () => 40)); //2

expand 扩展

根据现有的List,指定一个规则,生成一个新的Iterable集合。原数组不变

  1. var s1 = [1, 2, 3];
  2. print(s1.expand((e) => ([e + 1, e + 2]))); //Iterator (2, 3, 3, 4, 4, 5)
  3. print(s1); //[1, 2, 3]

递归

reduce

reduce((a, b) => (操作)) 用指定的方法对数组元素做连续操作,返回结果。原数组不变

  1. var s1 = [1, 2, 3, 4, 5];
  2. print(s1.reduce((a, b) => a + b)); //15 1+2+3+4+5
  3. print(s1.reduce((a, b) => a * b)); //120 1*2*3*4*5
  4. print(s1); //[1, 2, 3, 4, 5]

fold

fold(initValue, (preValue, element) => (操作)) 类似js的reduce第2个参数传递了初始值。
根据现有的List和给定的initValue,指定一个参数函数规则,对List每个元素做操作,并将结果返回。

  1. var s1 = [1, 2, 3, 4, 5];
  2. var s2 = s1.fold(2, (a, element) => (a + element)); //17 2+1+2+3+4+5
  3. print(s2); //[1, 2, 3, 4, 5]
  4. print(s1); //[1, 2, 3, 4, 5]

cast 将List的泛型提升到其父祖类

  1. List<String> s1 = ['aaa', 'bbb', 'ccc'];
  2. List<Object> s2 = s1.cast(); //类型提升,s2现在类型提升为s1的类型,即 List<String>
  3. s2.add('1'); //必须添加同类型的元素 如果 s2.add(1) 就会报错
  4. print(s2); //['aaa', 'bbb', 'ccc', '1'];