dart学习之旅(三):集合类型

136 阅读7分钟

在Dart中,也跟其他编程语言一样,拥有集合类型,分为有序集合和无序集合,其实上一篇文章中就有简单介绍过,就是有序集合Lists和无序集合Maps和无序并且无重复项的集合Sets,接下来就详细介绍下它们。

Lists

正如官方文档所说,Perhaps the most common collection in nearly every programming language is the *array*, or ordered group of objects,Dart肯定也是有list的。跟其他 编程语言一样,list是有序集合,它可以存储一系列的有序元素,元素的类型可以是任意类型,比如常见的数字、字符串、布尔值、对象、一个新的list,同样,他也拥有自己的内置方法和功能。

初试List

字面量创建

//字面量创建
var list = [1,2,3];
 //而且你可以在list中的最后一项添加逗号`,`并且不会影响到list,这样非常有利于咱们粘贴复制 哈哈哈 
 var test  =[
  'red',
  'pink',
  'green',
];
  

构造函数创建

Dart的list拥有如下几个构造函数

list.empty( bool Growthable = false })

创建一个新的空List,Growthable的默认值是false,如果是false,则List是长度为零的固定长度list,如果为true,则该list的可增长长度相当于<E>[],示例如下

final growableList = List.empty(growable: true); // []
growableList.add(1);
print(growableList);// [1]
​
//growable 为false 表示该list长度为0的固定list,不可添加数据,否则会报错
final fixedLengthList = List.empty(growable: false);
fixedLengthList.add(1);
print(fixedLengthList);// error
List.filled ( int length , E fill , { bool Growthable = false } )

创建给定长度的list,并在每个位置填充默认数据,长度length必须是一个非负整数。

final zeroList = List<int>.filled(3, 0, growable: true); // [0, 0, 0] 创建一个包含3个0的列表,并且长度可以增加
List.from(Iterable elements, {bool growable = true})

创建一个来自另一个list的新的list,并且是深拷贝创建的

 final numbers = <num>[1, 2, 3];
 final listFrom = List<int>.from(numbers);
 listFrom.add(4);
 listFrom[0] = 10;
 print(listFrom); // [10, 2, 3,4]
 print(numbers); // [1, 2, 3]
List.generate(int length, E generator(int index), {boolgrowable = true})

创建一个具有长度的list,并且使用默认值为每个索引调用generate创建的值填充

final growableList =
    List<int>.generate(3, (int index) => index * index, growable: true);
print(growableList); // [0, 1, 4]
​
final fixedLengthList =
    List<int>.generate(4, (int index) => index * index, growable: false);
print(fixedLengthList); // [0, 1, 4, 9]
List.of(Iterable elements, {bool growable = true})

类似于list.from,同样是深拷贝

final numbers = <int>[1, 2, 3];
final listOf = List<num>.of(numbers);
listOf.add(4);
print(listOf); // [1, 2, 3, 4]
print(numbers); //[1, 2, 3]

而与list.from不同的是

 List<String> foo = new List.from(<int>[1, 2, 3]); // 运行时报错
 List<String> bar = new List.of(<int>[1, 2, 3]); // 编译报错

因而,更推荐使用list.of,因为咱们学习的Dart是强类型语言,而list.from可能会在未来淘汰,可以参考这篇文章

stackoverflow.com/questions/5…

List.unmodifiable(Iterable elements)

创建一个无法改变的集合

final numbers = <int>[1, 2, 3];
final unmodifiableList = List.unmodifiable(numbers); // [1, 2, 3]
unmodifiableList[1] = 87; // Throws.

常用操作List的方法

其实上面就有用到一些基础方法了,比如list.add(xxx)

开始学习方法前,Dart中的assert有必要先说明,它是一种用于调试和开发阶段的断言机制,它用于在特定条件满足时验证程序的正确性,如果条件不满足,则会抛出一个异常来指示问题所在。

使用格式如下:

assert(condition, optionalMessage);
  • condition: 必须是一个布尔表达式。如果表达式的结果为 true,则断言通过,程序继续执行。如果表达式的结果为 false,则断言失败,抛出一个 AssertionError 异常。
  • optionalMessage: 可选参数,用于提供在断言失败时打印的额外信息。这个参数可以是任何类型的值,通常是一个字符串。

assert 通常在开发和调试阶段使用,用于检查一些假设和不变量是否满足。在发布(release)模式下,默认情况下,assert 语句会被忽略,因此对性能没有影响。但在调试模式(debug)下,assert 会被执行。

示例:

dartCopy code
void divide(int a, int b) {
  assert(b != 0, "The divisor 'b' must not be zero.");
  print(a ~/ b); // 使用 ~/ 运算符进行整数除法
}

void main() {
  divide(10, 2); // 输出: 5
  divide(10, 0); // 在调试模式下会抛出 AssertionError,并显示指定的错误消息
}

在上面的示例中,assert(b != 0, "The divisor 'b' must not be zero.") 用于确保在进行除法操作时,除数 b 不为零。如果 b 为零,断言就会失败,并在调试模式下抛出异常,同时输出指定的错误消息。在发布模式下,这个断言会被忽略,对程序运行没有影响。

注意:assert 应该用于验证在正常运行的情况下不应该发生的条件。如果你需要处理可能发生的错误或异常情况,应该使用异常处理机制(try-catch)来更好地处理这些情况。

list主要操作方法如下:
// 字面量创建 空的数组
var fruits =<String>[];
assert(fruits.isEmpty);//校验是否为空,不为空则控制台报错
print(fruits); //[]

// add 一次添加一个
fruits.add('kiwis');
print(fruits); //['kiwis']

//addAll 一次添加多个
fruits.addAll(['grapes', 'bananas']);
print(fruits); //['kiwis','grapes', 'bananas']

// 同样的也拥有length 常用的操作方法都使用,就不一一举例了	
print(fruits.length);//3

//删除指定下标元素
var kiwisIndex = fruits.indexOf('kiwis');
fruits.removeAt(kiwisIndex);
print(fruits); //['grapes', 'bananas']

//删除list中首个个匹配的元素
fruits.remove('grapes');
print(fruits);//['bananas']

//清空数组
fruits.clear();
assert(fruits.isEmpty);//校验通过
print(fruits);//[]

//获取下标 ,不存在则返回-1
var bananasIndex = fruits.indexOf('bananas');
print(bananasIndex); //1

//指定的下标处插入一个元素
fruits.insert(0, 'apple');
print(fruits);//['apple', 'bananas']

//检查list中是否包含指定元素,包含返回true,否则返回false
print(fruits.contains('kiwis')); //false

//检查list中是否包含多个指定元素 包含返回true 否则返回false
print(fruits.containsAll('apple', 'bananas')); true
//排序
var list = [4, 3, 1, 2];
list.sort();
print(list);[1,2,3,4]
  

Maps

同理,与其他语言一样,是一个无序的键值对集合,都可以在 运行时对其进行删除和添加的操作。这同样的是程序编程中最常用的数据结构。

//创建空的Map
var emptyMap = {};

//创建并初始化值的Map
var nobleGases = {
  2: 'helium',
  10: 'neon',
  18: 'argon',
};

//构造函数创建  在dart 中 new Map 中的new 关键字是可选的,可以不写
var nobleGases = Map<int, String>();
常用的操作方法
var myMap = {
  'key1': 'value1',
  'key2': 'value2',
};
//访问
print(myMap['key1']); //value1

//修改
myMap['key2'] = 'new value2';
print(myMap['key2']);  // new value2

//删除
myMap.remove('key1');
print(myMap); //{key2: new value2}

//检查map中是否含有某个key 有返回true 否则返回false
print(myMap.containsKey('key2')); //true

//检查map中是否有含有某个value  有返回true 否则返回false
print(myMap.containsValue('new value2'));//true

//添加 合并其他map的键值对  注意,有相同的key的话会把合并过来的key赋值给原来的key的对应的值
myMap.addAll({'key4': 'value4', 'key2': 'value2'});
print(myMap);//{'key4': 'value4', 'key2': 'value2'}

//删除所有键值对
myMap.clear();
print(myMap);//{}

Sets

同maps一样,都是无序集合,只不过这个Sets存储的元素都是唯一的,不存在重复项。

//创建空的set
var emptySet = <String>{};

//创建并初始化值的Set
ingredients.addAll(['gold', 'titanium', 'xenon']);

构造函数创建Set

//类似map中的from
final numbers = <num>{10, 20, 30};
final setFrom = Set<int>.from(numbers);
print(setFrom); // {10, 20, 30}

//创建一个空的Set
final emptySet = Set.identity();
print(emptySet);//{}

//类似Map的of
final baseSet = <int>{1, 2, 3};
final setOf = Set<num>.of(baseSet);
print(setOf); // {1, 2, 3}

//这个类似于Set.of的效果,只不过返回的set不能修改,否则控制台报错
  final characters = <String>{'A', 'B', 'C'};
  final unmodifiableSet = Set.unmodifiable(characters);
  unmodifiableSet.add('444');  //error
  print(unmodifiableSet);

常用的操作方法

//添加
var mySet = Set();
mySet.add(1);
print(mySet);

//添加多个
mySet.addAll([2, 3, 4, 5]);
print(mySet);//{1,2,3,4,5}

//删除
mySet.remove(1);
print(mySet);//{2,3,4,5}

//删除多个
mySet.removeAll([2, 3]);
print(mySet);//{4,5}

//清空
mySet.clear();
print(mySet);//{}

//检查元素是否在set中 在 返回true 不在返回false
 print(mySet.contains(5));//true

//检查多个元素是否在set中,再返回true 否则返回false
print(mySet.containsAll([4, 5,6])); //false

最后

本文只是简单介绍了一下,其实ListMapSet还有好多方法没有写出来,后面如果用上了还会继续说明,如果你先提前了解,可以查阅官方文档,文档很详细的描述了它们的对应的属性、操作符和方法。以下是链接:

Lists

api.dart.cn/stable/3.0.…

Maps

api.dart.cn/stable/3.0.…

Sets

api.dart.cn/stable/3.0.…