1、变量和常量
1.1、变量
Dart语言中所有变量都是一个对象,每个对象都是一个类的实例。数字类型(numbers)、函数和 null 也是对象。所有对象都继承自 Object 类。
Dart中定义变量的方式有两种:
1、明确的指定变量的数据类型
String name;
int age;
double height;
2、使用 var / dynamic / Object 声明变量
var message1;
message1 = "str";
message1 = 19; //这行代码会报错
dynamic message2;
message2 = 1.78;
message2 = "message2";//这行代码不会报错
print("${message2.length}");
Object message3;
message3 = 10;
message3 = "message3";
print("${message3.lenngth}"); //这句代码会报错
var与dynamic的区别
- 1.var声明的变量一经赋值后,数据类型就已经确定,不可以接收其他的数据类型,所以message1 = 19这行代码报错
- 2.dynamic声明的变量在第一次赋值后,可以继续接收其他的数据类型,所以message2 = "message2"这行代码不会报错
dynamic与Object的区别
- 1.dynamic与Object声明的变量都可以再次接收其他类型的数据类型
- 2.dynamic声明的变量可以使用变量运行时的属性跟方法,String类型的变量有length属性,所以可以使用,Object声明的变量只能使用Object本身的属性以及方法,Object类型本身不具备lehgth属性,所以print("${message3.lenngth}");这行代码会报错
1.2、final与const声明常量
const str = "sj";
final msg = "msg";
常量总结: 1.const与final 都用于声明常量,而且已经赋值都不可以被修改 2.const声明常量时,必须赋值明确的值,final声明的常量可以在运行时再赋值
2、数值型
Dart内置了一些类型
- 1、Number:数值型
- 2、String:字符串
- 3、Boolean:布尔型
- 4、List:列表
- 5、Map:键值对
- 6、Runes:符号字符
- 7、Symbols:标示符
2.1、数值型
数值型分为整形int和浮点型double。可以用num、int、double声明。
num声明的变量加入的是int型,还可以被改为double型。但是反过来int声明的变量不能在赋值为double型。
比如正确的
num a = 10;
a = 10.0;
错误的
int a = 10;
a = 10.0;
我们看一下源码就可以理解了
abstract class int extends num {}
abstract class double extends num {}
2.2、数值型操作
- 1、运算符:+、-、*、/、~/、%
- ~/这个是dart中独有的,表示取整
- 2、常用属性:isNaN、isEvent、isOdd等
- sEvent:是否是偶数
- isOdd:是否是奇数
- 3、常用方法:round()、floor()、ceil()、toInt()、toDouble()、abs()
- round():四舍五入
- floor():不大于的最大整数
- ceil():不小于的最小整数
- abs():绝对值
int e = -20;
print(e.abs());//绝对值 20
double f = 10.5;
print(f.round());//四舍五入 11
print(f.floor());//不大于的最大整数 10;
print(f.ceil());//不小于的最小整数 11
print(f.toInt());//转成int 10;
print(b.toDouble());//转double 12.0
print(a.toInt());
3、字符串
3.1、字符串的创建
1、字符串定义
使用单引号或双引号
String a = "abcdefg";
String b = '12345';
2、创建多行字符串,保留内在格式
使用三个单引号或三个双引号 创建多行字符串,保留内在格式,如换行和缩进等,里面写什么输出就是什么。
- 三个单引号
String e = '''asd
fdsd
fff
''';
- 三个双引号
String f = """ 1
2
3
4
""";
3、使用r创建原始raw字符串(转义字符等特殊字符会输出出来,而不会自动被转义)
String str1=r'Hello \n World'
3.2、字符串常用属性
1、常规属性
String a20 = "aaaa";
String a21 = "";
- 1、字符串长度
print(a20.length);//4
- 2、是否为空
print(a20.isEmpty);//false
print(a21.isEmpty);//true
- 3、是否不为空
print(a20.isNotEmpty);//true
print(a21.isNotEmpty);//false
2、字符串连接
String a = "abcdefg";
String b = '12345';
- 1、使用+号连接
String c = a + b; //使用+号连接
print(c); //abcdefg12345
- 2、使用相邻空格符号连接,必须是两个字符串 不能是变量
String d = 'aaa' 'bbb'; //使用相邻空格符号连接,必须是两个字符串 不能是变量
print(d); //aaabbb
3、字符串模板,使用${} 将一个字符串变量/表达式嵌入到另一个字符串内
- 1、变量
String a1 = "aa";
String b1 = "bb${a1}bb";
print(b1); //bbaabb
- 2、表达式
String a1 = "aa";
String b2 = "bb${a1.toUpperCase()}bb";
print(b2); //bbAAbb
4、字符串与数字之间的转换
- 1、字符串转int数值
int int1 = int.parse("33");
print(int1); //33
- 2、字符串转double数值
double d1 = double.parse("3.33");
print(d1); //3.33
- 3、数值转字符串
print(33.toString());
print(3.34.toString());
- 4、数值转字符串保留精度
print(3.12345.toStringAsFixed(3)); //保留精度 3.123
5、字符串切割
String a2 = "aaabbb";
- 1、含头不含尾
print(a2.substring(0, 2)); //aa 含头不含尾
- 2、从指定index至末尾
print(a2.substring(3)); //bbb 从指定index至末尾
- 3、使用,分割,返回的是一个数组
String a5 = "a,d,d d,c,,";
List<String> a6 = a5.split(",");//使用,分割,返回的是一个数组
print(a6.length); //6
print(a6);//[a, d, d d, c, , ];
- 4、正则匹配,拆分字符串
String strB = "abba";
print(strB.split(new RegExp(r"b*")));
- 5、查询,并替换
String a8 = "a b,c";
String a7 = a8.splitMapJoin(",",//查询“,”,用onMatch的返回值替换“,”用onNonMatch的返回值替换其他
onMatch: (Match match) {
return "a";
}, onNonMatch: (String nonMatch) {
return "b";
});
print(a7);//bab a b,c => bab
6、字符串判断 是否包含或以xxx开始结束等
String a3 = "aaabbbccc";
- 1、是否以‘xxx’开头
print(a3.startsWith("aa")); //true
print(a3.startsWith("aa", 3)); //false 从index=3开始判断
- 2、是否以‘xxx’结尾
print(a3.endsWith("c")); //true
- 3、是否包含‘xxx’
print(a3.contains("ab")); //true
print(a3.contains("ac")); //false
- 4、从某处开始是否包含‘xxx’
print(a3.contains("ab", 3)); //false 从index=3开始判断
7、字符串替换
String a4 = "abcdeab";
- 替换全部符合条件的
print(a4.replaceAll("ab","cc"));//cccdecc 替换全部符合条件的
- 只替换第一个符合条件的
print(a4.replaceFirst("ab", "dd"));//ddcdeab 只替换第一个符合条件的
- 从index=3开始 替换第一个符合条件的
print(a4.replaceFirst("ab", "dd",3));//abcdedd 从index=3开始 替换第一个符合条件的
- 范围替换 从0-3 含0不含3
print(a4.replaceRange(1, 3, "z"));// 范围替换 从0-3 含0不含3
- 用方法返回值替换指定的字符串
print(a4.replaceAllMapped("c", (Match match){//abyydeab 用方法返回值替换指定的字符串
return "yy";
}));
- 从index=2开始 用方法返回值替换指定的字符串
//abcdea333 从index=2开始 用方法返回值替换指定的字符串
print(a4.replaceFirstMapped("b", (Match match){
return "333";
},2));
8、字符串查找
String a9 = "aababcc1bc23";
- 获取指定字符出现的位置
String str = 'Dartisans';
print(str.indexOf('art'));
print(str.indexOf(new RegExp(r'[A-Z][a-z]')));
print(str.lastIndexOf('a'));
print(str.lastIndexOf(new RegExp(r'a(r|n)')));
- 第一个符合条件的index
print(a9.indexOf("ab"));//1
- 从index=xx开始往后找
print(a9.indexOf("ab",2));//3 从index=2开始往后找
print(a9.indexOf("ab",4));//-1 从index=4开始往后找,找不到返回-1
- 从后往前找 返回第一个符合条件的index
print(a9.lastIndexOf("bc"));//8 从后往前找 返回第一个符合条件的index
- 从后往前找 从index=xxx开始找 返回第一个符合条件的index 找不到返回-1
//-1 从后往前找 从index=3开始找 返回第一个符合条件的index 找不到返回-1
print(a9.lastIndexOf("bc",3));
//4 从后往前找 从index=7开始找 返回第一个符合条件的index
print(a9.lastIndexOf("bc",7));
9、去除空格
String a11 = " aab bcc ";
print(a11);// aab bcc
- 去除左右两边空格
print(a11.trim());//aab bcc 去除左右两边空格
- 去除右边空格
print(a11.trimRight());// aab bcc 去除右边空格
- 去除左边空格
print(a11.trimLeft());// aab bcc //去除左边空格
10、补齐长度 剩余位使用指定字符串替换
String a13 = "111";
- 剩余3个位 默认使用""补齐
print(a13.padLeft(6));// 111 剩余3个位 默认使用""补齐
- 剩余3个位 指定使用"c
print(a13.padRight(6,"c")); //111ccc 剩余3个位 指定使用"c"
- 剩余3个位 每个位指定使用"dd" 替换后总长度不是6
print(a13.padRight(6,"dd")); //111dddddd 剩余3个位 每个位指定使用"dd" 替换后总长度不是6
- 如果指定长度小于原字符串长度 返回原字符串
print(a13.padLeft(2,"e"));//111 如果指定长度小于原字符串长度 返回原字符串
11、字符串先后比较
String a12 = "bbcc";
print(a12.compareTo("aaa"));//1 在ascii码中 b>a
print(a12.compareTo("bbcc"));//0
print(a12.compareTo("dd"));//-1 在ascii码中 b<d
12、字符串Unicode编码
- codeUnitAt(方法返回给定索引处的16位UTF-16代码单元)
- 参数 index- 表示字符串中的字符索引。
- 返回值 返回一个数字值。
String.codeUnitAt(int index)
void main() {
var res = "Good Day";
print("Code Unit of index 0 (G): ${res.codeUnitAt(0)}");
}
Code Unit of index 0 (G): 71
- codeUnits(属性返回给定字符串的UTF-16代码单元列表)
String.codeUnits
void main() { String str = "Hello"; print(str.codeUnits); }
[72, 101, 108, 108, 111]
13、字符串运算符(+、==、[])
- +:加好运算符,字符串拼接功能
String a = 'abc';
String b = 'cbd';
print(a+b);//abccbd
- ==:等号运算符,比较两个字符串是否相同
String a = 'abc';
String b = '2';
if(a == b){
print('true');
}else{
print('false');
}//返回false
- []:取值运算符,取出字符串索引位指向的单个字符
String a = 'abc';
String b = '2'; print(a[1]);//b
4、List
1、声明
var list1 = List();// 不限定长度,不限定类型,可添加任意类型的数据
List list2 = List();// 不限定长度,不限定类型,可添加任意类型的数据
List list3 = List(2);//限定了长度为2 越界会报错,不限定类型,可添加任意类型的数据
list1.add(1);
list1.add('aaa');
list1.add(true);
print(list1);//[1, abc, true]
var list4 = [1,2,3];//初始就赋值了,限定了长度,限定了类型,只能是int
var list5 = [2,'3',true];//初始就赋值了,限定了长度,未限定类型,任意位置可用任意类型替换
List list6 = ['a',2,'b',false];//初始就赋值了,限定了长度,未限定类型,任意位置可用任意类型替换
list5[1] = 2;
list5[2] = 'aa';
print(list5);//[2, 2, aa]
var list33 = <String>["a","b"];
List<String> list7 = ['a','b','3'];
List<String> list8 = new List(2);
list8[0]=('aaa');
print(list8);//[aaa, null]
2、常用属性
List<String> list13 = List();
list13.add('aaa');
list13.add('bbb');
list13.add('ccc');
print(list13.length);//3 长度
print(list13.isEmpty);//false 是否为空
print(list13.isNotEmpty);//true 是否不为空
print(list13.reversed);//(ccc, bbb, aaa) 返回一个List的倒序排列的Iterable 不改变原List
print(list13.first);//aaa 第一个元素
print(list13.last);//ccc 最后一个元素
3、常用方法
1、增
- 1、add() 添加一个元素到List末尾
List<String> list9 = List();
list9.add('aaa');
list9.add('bbb');
print(list9);//[aaa, bbb]
- 2、addAll() 两个List合并
List<String> list10 = List();
list10.add('aaa');
list10.add('bbb');
List<String> list11 = List();
list11.add('ccc');
list11.add('ddd');
list11.addAll(list10);
print(list11);//[ccc, ddd, aaa, bbb]
- 3、insert(index,element) 在指定index处插入值
List<int> list21 = List();
list21.add(0);
list21.add(1);
list21.add(2);
list21.add(3);
print(list21);//[0, 1, 2, 3]
list21.insert(1, 5); //指定索引位置 插入值,其余顺延
print(list21);// [0, 5, 1, 2, 3]
- 4、insertAll(index,list) 在指定index处插入list 其余顺延
List<int> list25 = List();
list25.add(0);
list25.add(1);
list25.add(2);
list25.add(3);
print(list25);//[0, 1, 2, 3]
list25.insertAll(1, [5,6,7]);
print(list25);//[0, 5, 6, 7, 1, 2, 3]
- 5、followedBy(list) 将自身和参数内list合成一个List
List<int> list = [1,2,3];
Iterable<int> list1 = list.followedBy([4,5]);
print(list1);//(1, 2, 3, 4, 5)
2、删
- remove(obj) 删除具体的元素
- removeAt(index) 删除索引位置元素
- removeLast()删除末尾元素
- removeRange(start,end) 范围删除
- removeWhere() 根据条件删除:
- clear() 清空数组
void removeWhere(bool test(E element));
List<String> list = List();
list.add("aa");
list.add("bb");
list.add("cc");
list.add("dd");
list.add("ee");
list.add("ff");
//根据条件 筛选,这里表示删除元素值为dd
list.removeWhere((element){ return element=='dd';});
print(list);//[aa, bb, cc, ee, ff]
//条件只有一个表达式时,可以用箭头函数简化写法
list.removeWhere((element)=> element=='cc');
3、改
- 1、修改指定index位置的值
var list = [2,'3',true];
list[1] = 2;
- 2、setRange(startIndex,endIndex,list) 范围修改List的值
List<String> list = List();
list.add('aaa');
list.add('bbb');
list.add('ccc');
list.add('ddd');
print(list);// [aaa, bbb, ccc, ddd]
List<String> list1 = List();
list1.add("111");
list1.add("222");
list1.add("333");
list1.add("444");
list1.add("555");
list1.add("666");
list.setRange(0,3, list1);
//范围修改,从list1取出0 1 2位置的值,修改list对应0 1 2位置的值,0-3含头不含尾,start和end相同,则不变。
//start和end任何一个超出list list1的角标 则报错。
print(list);//[111, 222, ccc, ddd]
- 3、replaceRange(start,end,list)范围替换 含头不含尾
List<String> list = List();
list.add('aaa');
list.add('bbb');
list.add('ccc');
list.add('ddd');
print(list);// [aaa, bbb, ccc, ddd]
list.replaceRange(0,2,["1","2","3"]);
print(list);//[1, 2, 3, ccc, ddd]
- 4、fillRange(start,end,value) 从start-end 每个元素用value替换
List<String> list = List();
list.add('aaa');
list.add('bbb');
list.add('ccc');
list.add('ddd');
print(list);// [aaa, bbb, ccc, ddd]
list.fillRange(0,2,"1");
print(list);//[1, 1, ccc, ddd]
- 5、retainWhere(()=>(bool)) 根据条件筛选元素
List<String> list = List();
list.add('aaa');
list.add('bbb');
list.add('ccc');
list.add('ddd');
print(list);// [aaa, bbb, ccc, ddd]
list.retainWhere((element)=>(element=="aaa"));
print(list);//[aaa]
- 6、setAll(index,list) 从index开始,使用list内的元素逐个替换本list中的元素
List<String> list = List();
list.add('aaa');
list.add('bbb');
list.add('ccc');
list.add('ddd');
print(list);// [aaa, bbb, ccc, ddd]
list.setAll(1,["1","2"]);
print(list);//[aaa, 1, 2, ddd]
4、查
- 1、indexOf(element,[start]) 查找指定元素在list中的索引
- 2、lastIndexOf(obj,index) 从后往前查找,返回第一个的index
- 3、elementAt(index) 获取指定索引位置的元素
- 4、any((element)=>(bool)) 判断List中是否有任意一个元素符合给定的参数
List<String> list = List();
list.add('aaa');
list.add('bbb');
list.add('ccc');
list.add('ddd');
//判断list元素中是否有任何一个元素满足给定的条件,如果满足返回true 否则false
bool result = list.any((element)=>(element=="aa"));
print(result);//false
- 5、every((element)=>(bool)) 判断List中是否每个元素都符合参数函数
List<int> list1 = [1, 2, 3, 4, 5];
//是否每个元素都符合条件 都符合返回true 否则返回false
bool result1 = list1.every((element)=>(element%2==0));
- 6、contains(obj) List中是否存在给定的obj
- 7、firstWhere((element)=>(bool)) 返回第一个满足条件的元素(不是元素的index)
List<int> list1 = [1, 2, 3, 4, 5];
//返回满足条件的第一个元素
int result = list1.firstWhere((ele)=>(ele>3));
print(result);//4
- 8、lastIndexWhere((e)=>(bool)) 从后向前找 返回第一个满足条件的元素的index
- 9、lastWhere((e)=>(bool)) 从后往前找,返回第一个满足条件的元素的值(不是index)
- 10、forEach() List遍历每个元素
List<String> list = List();
list.add('aaa');
list.add('bbb');
list.add('ccc');
list.add('ddd');
//遍历每个元素 此时不可add或remove 否则报错 但可以修改元素值
list.forEach((ele){
print(ele);
});
for(var x in list){
print(x);
}
- 11、map() 遍历现有List的每个元素,并做处理,返回一个新的Iterable
List<int> list = [1,2,3];
Iterable<String> list1 = list.map((ele)=>(ele>2?"a":"b"));
print(list1);//(b, b, a)
- 12、fold(initValue,(preValue,element)=>()); 根据现有的List和给定的initValue,指定一个参数函数规则,对List每个元素做操作,并将结果返回。
List<int> list = [1,2,3];
int result = list.fold(2,(a,ele)=>(a*ele));
print(result);//12
- 13、reduce((a,b)=>(某种操作)) 用指定的方法对元素做连续操作,将结果返回
List<int> list = [1,2,3];
int result = list.reduce((a,b)=>(a+b));
print(result);//6
- 14、skip
- skip(count)越过count个元素后,开始返回list的Iterable
- skipWhile((e)=>(bool)) 根据参数函数,找到第一个不符合条件的元素,然后将其及其后的元素返回
List<int> list = [3, 4, 5, 2, 1];
//越过count个元素后,开始返回list的Iterable
Iterable<int> result = list.skip(2);
print(result);//(5, 2, 1)
//从第一个元素开始,逐个判断是否符合参数函数,直至第一个不符合的元素,将其及其后面的元素返回
Iterable<int> result1 = list.skipWhile((e)=>(e>2));
print(result1.toList());//[2, 1]
- 15、take
- take(count) 从0开始取count个元素,并返回结果
- takeWhile((e)=>(bool)) 从0开始取,直至第一个不符合函数的元素,将其前面的元素都返回。
List<int> list = [3, 4, 1, 2, 5];
//从0开始取2个元素 并返回
Iterable<int> result = list.take(2);
print(result);//(3, 4)
//从第一个元素开始,逐个判断是否符合参数函数,直至第一个不符合的元素,将其前面元素都返回
Iterable<int> result1 = list.takeWhile((e)=>(e>2));
print(result1);//(3, 4)
- 16、where
1、where((e)=>(bool) 根据指定参数函数筛选每个元素,符合条件的元素组成一个新的Iterable
List<int> list = [3, 4, 1, 2, 5,2,3,6];
//根据参数函数筛选
Iterable<int> result = list.where((e)=>(e>2));
print(result);//(3, 4, 5, 3, 6)
2、singleWhere((e)=>(bool>) 找到那唯一满足条件的元素
List<int> list = [3, 4, 1, 2, 5];
//找到那唯一满足条件的元素,如果没有满足条件的元素或有多个元素满足条件,就返回orElse方法的返回值,如果没有传入orElse则报错。
int result = list.singleWhere((e)=>(e>4),orElse: ()=>(10));
print(result);//5
3、whereType() 从无指定泛型的List中,筛选出指定类型的数据。
List list = [3, 4, "a",true,"b",5,false];
//从混合类型的List中,筛选出指定类型的数据
Iterable<int> result = list.whereType();
print(result);//(3, 4, 5)
Iterable<String> result1 = list.whereType();
print(result1);//(a, b)
Iterable<bool> result2 = list.whereType();
print(result);//(true, false)
- 17、expand() 根据现有的List,指定一个规则,生成一个新的List
List<int> list = [1, 2, 3, 4, 5];
//通过对元素操作,返回一组指定规则的新的集合
Iterable<int> result = list.expand((element)=>([element+1,element+2]));
print(result);//(2, 3, 3, 4, 4, 5, 5, 6, 6, 7)
- 18、toSet() 将List转为Set 去除后面重复的元素
List<int> list = [3, 4, 1, 2, 5,2,3,6];
//将list转为set,将后面重复的都去掉
Set<int> result = list.toSet();
print(result);//{3, 4, 1, 2, 5, 6}
- 19、asMap() 将list转为map
List<String> list = List();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
list.add("eee");
print(list);// [aaa, bbb, ccc, ddd, eee]
Map<int,String> map = list.asMap();//list转为map key为index value为list的值
print(map);//{0: aaa, 1: bbb, 2: ccc, 3: ddd, 4: eee}
- 20、sort() List自身排序
List<int> list20 = List();
list20.add(2);
list20.add(3);
list20.add(1);
list20.add(0);
// print(list20);//[2, 3, 1, 0]
list20.sort((a,b)=>(a>b?1:-1));//自身排序 修改本身的list
// print(list20);//[0, 1, 2, 3]
- 21、sublist(start,[end]) 从指定index 截取list
List<int> list21 = List();
list21.add(0);
list21.add(1);
list21.add(2);
list21.add(3);
print(list21);//[0, 1, 2, 3]
list21.insert(1, 5); //指定索引位置 插入值,其余顺延
print(list21);// [0, 5, 1, 2, 3]
List<int> list22 = list21.sublist(1);//从指定索引截取List
List<int> list23 = list21.sublist(1,3);//从指定索引截取List 含头不含尾
print(list22);//[5, 1, 2, 3]
print(list23);//[5, 1]
- 22、getRange(start,end) 从list中截取start-end范围内的数据
List<int> list28 = List();
list28.add(0);
list28.add(1);
list28.add(2);
list28.add(3);
list28.add(4);
list28.add(5);
list28.add(6);
list28.add(7);
// print(list28);//[0, 1, 2, 3, 4, 5, 6, 7]
Iterable<int> list29 = list28.getRange(2, 5);//含头不含尾,从2开始到5(不含)结束的一个Iterable
// print(list29);//(2, 3, 4)
- 23、join("-") 用指定的字符将List中每个元素都连接起来,返回一个字符串
List<int> list50 = [3, 4, 1, 2, 5];
String result24 = list50.join("-");//用指定的字符将每个元素都连接起来,返回一个字符串
// print(result24);//3-4-1-2-5
5、Map
在Dart中,Map是以key-value形式存储,键和值都可以是任何类型的对象,每个键只能出现一次
1、声明
- 1、通过直接声明的方式创建一个Map
Map game = {"game":"Switch","company":"任天堂"};
- 2、创建一个不可变的Map,需要在Map前面加一个const
Map game = const{"game":"Switch","company":"任天堂"};
- 3、构造方式声明
Map game = new Map();
game['name'] = '任天堂';
2、属性
print(citys.length); //长度
print(citys.isEmpty); //是否为空
print(citys.isNotEmpty); //是否不为空
print(citys.keys);// key的集合
print(citys.values);//value的集合
//(MapEntry(cityname: 北京), MapEntry(cityid: 10001), MapEntry(1: 1))
print(citys.entries);// map迭代的键值对集合
3、方法
citys.update('1', (value)=>(value+'23')); //存在的值可以直接修改,不存在的值就直接报错
print(citys);
//key不存在,因为用ifAbsent参数, 返回ifAbsent函数的值,并添加到map中
citys.update('2', (value)=>(value+'34'), ifAbsent: ()=>('123'));
print(citys);
//updateAll根据参数函数的规则,批量修改app
Map<String,int> map1 = {'a':1,"b":2,"c":3}; //指定泛型初始化map
map1.updateAll((k,v){
return v*2;
});
print(map1);
map1.updateAll((k,v){
if(k=='a'){return 100;}
if(k=='b'){return 200;}
return v*10;
});
print(map1);
//删除一个key remove
map1.remove('a');
print(map1);
//根据条件批量删除
Map<String,int> map10 = {"a":1,"b":2,"c":3,"d":4,"e":5};
map10.removeWhere((k,v)=>(v>3)); //删掉符号参数函数keyvalue对
print(map10); //{a: 1, b: 2, c: 3}
//是否包含
map10.containsKey('a'); //是否包含key
map10.containsValue(1); //是否包含value
4、遍历
names.forEach((k,v){ //forEach 遍历
print('遍历 $k , $v');
});
names.map((k,v){ //map方法放回一个新的数组
return MapEntry(v, k);
});
print('map: $names');
5、清空
//清空map
names.clear();
print('names $names');
6、添加addall
Map<String,int> map11 = {'a':1,'b':2,'c':3};
Map<String,int> map12 = {'d':3,'e':5,'f':5,'c':10};
//addAll 整体合并另一个map,泛型要一致 key相同时value值后者覆盖前者.前者不存在就添加进来
map11.addAll(map12);
print(map11);
//addEntries 合并两个map,如果key有重复,并合并的map的value覆盖前者
map11.addEntries(map12.entries);
print(map11);
//putlfAbsent() 存在就获取值,不存在则添加到map,然后返回值
int result= map12.putIfAbsent('c', ()=>(100)); //存在
print(result); //10
int result2 = map12.putIfAbsent('t', ()=>1000); //不存在
print(result2);
print(map12); //map中也会跟着添加进去
7、cast 泛型类型提升为其父祖类
//cast() 泛型类型提升为其父祖类
Map<String,int> map21 = {"a":1,"b":2,"c":3};
Map<Object,Object> map22 = map21.cast();
map22["d"]=33;
// print(map22);//{a: 1, b: 2, c: 3, d: 33}
6、dynamic&Object
dynamic: [daɪˈnæmɪk] 动态的;动力的;动力学的;有活力的
基础
在Dart里面,一切皆对象,而且这些对象的父类都是Object。 当没有明确类型的时候,编译的时候回根据值明确类型
var name1 = "abc";
Object name2 = "def";
dynamic name3 = "hij";
以上写法都没有问题,但是Dart不建议我们这么做。在实际开发过程中,我么么应该尽量为变量确定一个类型,这样可以提高安全性,加快运行速度。
如果不指定类型,debug模式下类型会是动态的。
使用dynamic时,则告诉编译器,我们不用做类型检测,并且知道自己在做什么。如果我们调用了一个不存在的方法时,回执行noSuchMethod()方法。 在默认情况下(Object里实现)它会抛出NoSuchMethodError
dynamic,var,object三者的区别
void main()//dynamic,var,object三者的区别
{
//dynamic
dynamic x = 'hello';//编译时不会揣测数据类型,但是运行时会推断
print(x.runtimeType);//String
print(x);
//但是这样的坏处就是会让dart的语法检查失效,所以有可能会造成混乱而不报错
//所以不要直接使用dynamic
x = 123;
print(x.runtimeType);//int,说明类型是可变的
print(x);
//var
var a = 'hello';
print(a.runtimeType);
print(a);
//a = 123;//会报错
a = '123';
print(a);
//Object
Object w = 1;
print(w.runtimeType);
print(w);
//不能调用Object不存在的方法
}
dynamic与Object的最大的区别在于静态类型检查上
7、运算符
我们都知道计算机高级语言都有大同小异的运算符,那接下来让我们来看看Dart有哪些运算符。
使用运算符时,可以创建表达式。 以下是运算符表达式的一些示例:
a++
a + b
a = b
a == b
c ? a : b
a is T
在运算符表中,每个运算符的优先级高于其后面行中的运算符。 例如,运算符%的优先级高于运算符==,它的优先级高于逻辑与运算符&&。 该优先级意味着以下两行代码执行相同的方式:
// Parentheses improve readability.
if ((n % i == 0) && (d % i == 0)) ...
// Harder to read, but equivalent.
if (n % i == 0 && d % i == 0) ...
算术运算符
Dart支持通常的算术运算符,如下表所示。
要测试两个对象x和y是否表示相同的东西,请使用==运算符。 (在极少数情况下,你需要知道两个对象是否完全相同,请使用identical()函数。)以下是==运算符的工作原理:
- 果x或y为null,则如果两者都为null则返回true;如果只有一个为null,则返回false。
- 回调用方法 x.==(y)的结果。 (没错,运算符如==是在第一个操作数上调用的方法。你甚至可以覆盖许多运算符,包括 == )
assert(2 == 2);
assert(2 != 3);
assert(3 > 2);
assert(2 < 3);
assert(3 >= 3);
assert(2 <= 3);
运算符
as,is,is! 运算符在运行时检查类型很方便。
当 obj是指定接口T的实现,那么obj is T的结果是 true. 举个例子, obj is Object永远是true。 使用as运算符将对象强制转换为特定类型。 通常,你应该为了缩短一个对象使用之前,对该对象做is测试。
if (emp is Person) {
// Type check
emp.firstName = 'Bob';
}
你可以使用as运算符缩短代码:
(emp as Person).firstName = 'Bob';
注意:这两段代码不是相同的,如果emp是null 或者不是一个Person, 那么第一个例子(用is的)不会做任何事;第二个例子(用as的)会抛出一个异常。
赋值运算符
如你所见,你可以使用=运算符指定值。 要仅在变量为null时赋值,请使用??=运算符。
// Assign value to a
a = value;
// Assign value to b if b is null; otherwise, b stays the same
// b为null时才会赋值,不为null不会改变b的值
b ??= value;
复合赋值运算符(如+=)将运算与赋值组合在一起。
逻辑运算符
你可以使用逻辑运算符反转或组合布尔表达式。
if (!done && (col == 0 || col == 3)) {
// ...Do something...
}
条件表达式
Dart有两个运算符,可以让你简单的得出需要if-else语句表达式的结果: condition? expr1 : expr2 如果condition为true,则计算expr1(并返回其值); 否则,计算并返回expr2的值。 expr1 ?? expr2 如果expr1为非null,则返回其值; 否则,计算并返回expr2的值。
当你需要根据布尔表达式赋值时,请考虑使用?:
var visibility = isPublic ? 'public' : 'private';
如果布尔表达式测试null,考虑使用??
String playerName(String name) => name ?? 'Guest';
级联符号(..)
Cascades(..)允许你对同一对象进行一系列操作。 除了函数调用,你还可以访问同一对象上的字段。 这通常可以为您节省创建临时变量的步骤,并允许你编写更多流畅的代码。
querySelector('#confirm') // Get an object.
..text = 'Confirm' // Use its members.
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
第一个方法调用querySelector()返回一个选择器对象。 级联表示法后面的代码对此选择器对象进行操作,忽略可能返回的任何后续值。
前面的例子等同于:
var button = querySelector('#confirm');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => window.alert('Confirmed!'));
你也可以嵌套级联:
final addressBook = (AddressBookBuilder()
..name = 'jenny'
..email = 'jenny@example.com'
..phone = (PhoneNumberBuilder()
..number = '415-555-0100'
..label = 'home')
.build())
.build();
小心在返回实际对象的函数上构造级联。 例如,以下失败代码:
var sb = StringBuffer();
sb.write('foo')
..write('bar'); // Error: method 'write' isn't defined for 'void'.
调用sb.write()返回了 void,然而你不能在void 上构造一个级联
注意:严格来说,级联的“双点”符号不是运算符。 它只是Dart语法的一部分。
8、函数
Dart是一门面向对象的语言,所以函数也是对象,并且函数的类型是Function。
1、函数的基本使用
函数的参数可以分成两类: 必须参数和可选参数
可选参数可以分为 命名可选参数 和 位置可选参数
定义方式:
命名可选参数: {param1, param2, ...}
位置可选参数: [param1, param2, ...]
1、main函数
每个应用程序都必须有一个顶层的main函数。它是一个应用程序的切入口。改main函数返回void并具有List的可选参数
void main() {
runApp(MyApp());
}
2、可选参数
可选的命名参数,即使不传递这些参数也是可以的。 在定义函数时,使用{param1,parqm2,...}指定命名参数。
void userSettings({int age,String name}){
if(age != null) {
print('my age is ${age}');
}
if(name != null) {
print('my name is ${name}');
}
}
上面函数中,我们可以传递age、name这两个参数,绘制其一,或者一个都不传递
3、必传参数
有时候,我们在调用函数的时候,必须传入一些参数,这个时候就用到了@required来修饰。使用@required有利于静态代码分析器进行检查
void userSettings({@required int age,String name}){
if(age != null) {
print('my age is ${age}');
}
if(name != null) {
print('my name is ${name}');
}
}
4、可选的位置参数
使用[]把目标标记为可选的位置参数
void userSettings(int age, String name, [String interests]){
if(age != null) {
print('my age is ${age}');
}
if(name != null) {
print('my name is ${name}');
}
if(interests != null){
print('兴趣是${interests}');
}
}
5、默认参数
默认值是编译时常量,在函数的参数后面使用 = 为参数赋值
- 参数可以有默认值, 在不传入的情况下, 使用默认值
- 注意, 只有可选参数才可以有默认值, 必须参数不能有默认值
void userSettings(int age, String name, [String interests,String sex = "男"]){
if(age != null) {
print('my age is ${age}');
}
if(name != null) {
print('my name is ${name}');
}
if(interests != null){
print('兴趣是${interests}');
}
if(sex != null){
print('性别${sex}');
}
}
6、函数作为参数
executeFunction(fn, [args]) {
if (fn != null) {
return fn(args);
}
}
7、函数作为变量
var say = (name){
pring(name);
}
say('小明');
2、箭头函数
List l1 = [1, 2];
l1.forEach((item) {
print(item);
});
l1.forEach((item) => print(item));
箭头函数只能有一行,可以省略大括号 在 map 方法中使用箭头函数:
var l2 = l1.map((item) {
return item % 2 == 0 ? item * 2 : item;
});
print(l2.toList());
var l3 = l1.map((item) => item % 2 == 0 ? item * 2 : item);
print(l3);
3、匿名函数
某些情况下,给函数命名太麻烦了,我们可以使用没有名字的函数,这种函数可以被称之为匿名函数( anonymous function),也可以叫lambda或者closure。
main(List<String> args) {
// 1.定义数组
var movies = ['盗梦空间', '星际穿越', '少年派', '大话西游'];
// 2.使用forEach遍历: 有名字的函数
printElement(item) {
print(item);
}
movies.forEach(printElement);
// 3.使用forEach遍历: 匿名函数
movies.forEach((item) {
print(item);
});
movies.forEach((item) => print(item));
}
4、立即执行函数
// 立即执行方法
((name) {
print('my name is ${name}');
})('postbird');
5、闭包
// 闭包
Function getA() {
int a = 0;
return () {
a++;
print(a);
};
}
Function b = getA();
b();
b();