欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Flutter中Dart集合使用教程

 更新時(shí)間:2022年05月10日 08:50:47   作者:島上碼農(nóng)  
集合是應(yīng)用程序中最為常見的數(shù)據(jù)結(jié)構(gòu),Dart一共支持四種集合,其中核心的List,?Map和Set在基礎(chǔ)框架中。本文將詳細(xì)講解Dart集合的最佳實(shí)踐,需要的可以參考一下

前言

集合是應(yīng)用程序中最為常見的數(shù)據(jù)結(jié)構(gòu),Dart 一共支持如下四種集合,其中核心的 ListMap 和 Set 在基礎(chǔ)框架中,而 Queue 在 dart:collection 庫定義。

  • 列表:也就是 List類,可動(dòng)態(tài)增長(zhǎng)的數(shù)組;
  • key-value 集:即 Map<K, V> 類,用于存儲(chǔ)鍵值對(duì);
  • 隊(duì)列:即 Queue類;
  • 集合:即Set類,集合中的元素不可重復(fù)。

本篇介紹集合的最佳實(shí)踐。

優(yōu)先使用集合的特有語法

對(duì)于核心的集合類ListMap 和 Set ,由于經(jīng)常使用,Dart 為這些類提供的內(nèi)置的語法來快速構(gòu)建這些集合對(duì)象。

//?推薦用法
var?points?=?<Point>[];
var?addresses?=?<String,?Address>{};
var?counts?=?<int>{};

//?不推薦
var?addresses?=?Map<String,?Address>();
var?counts?=?Set<int>();

集合還有一些特殊的用法,比如使用展開操作符(而且同時(shí)支持 ? 操作符判斷是否為空)將一個(gè)集合加入到另一個(gè)集合。同時(shí)還支持結(jié)合 if 和 for 來控制元素的加入。

//?推薦用法
var?arguments?=?[
??...options,
??command,
??...?modeFlags,
??for?(var?path?in?filePaths)
????if?(path.endsWith('.dart'))
??????path.replaceAll('.dart',?'.js')
];

//?不推薦
var?arguments?=?<String>[];
arguments.addAll(options);
arguments.add(command);
if?(modeFlags?!=?null)?arguments.addAll(modeFlags);
arguments.addAll(filePaths
????.where((path)?=>?path.endsWith('.dart'))
????.map((path)?=>?path.replaceAll('.dart',?'.js')));

上面的推薦用法其實(shí)除了展開操作符以外,使用 if 和 for 的并不常見。說實(shí)話,個(gè)人挺不習(xí)慣這種寫法的,感覺可讀性并不高。

不要使用.length 屬性判斷集合是不是為空

由于集合遵循的是 Iterable 協(xié)議,這個(gè)協(xié)議并不需要集合隨時(shí)知道它的長(zhǎng)度。因此調(diào)用.length 的時(shí)候,其實(shí)相當(dāng)于是遍歷了一遍,執(zhí)行速度是很低的。這是獲取 length 的實(shí)現(xiàn)方法:

int?get?length?{
??assert(this?is!?EfficientLengthIterable);
??int?count?=?0;
??Iterator?it?=?iterator;
??while?(it.moveNext())?{
????count++;
??}
??return?count;
}

因此,更高效地判斷集合是否為空的做法是使用.isEmpty 或 .isNotEmpty。

bool?get?isEmpty?=>?!iterator.moveNext();

因此,不要用.length == 0來判斷集合是否為空。

//?正確示例
if?(lunchBox.isEmpty)?return?'so?hungry...';
if?(words.isNotEmpty)?return?words.join('?');

//?錯(cuò)誤示例
if?(lunchBox.length?==?0)?return?'so?hungry...';
if?(!words.isEmpty)?return?words.join('?');

避免使用 forEach 迭代元素

在 JS 中,會(huì)使用 forEacth 方法來迭代元素,這是因?yàn)閮?nèi)置的 for-in 循環(huán)和我們想要的不一樣。但是在 Dart 中的 for-in 循環(huán)是正常的迭代,這樣會(huì)簡(jiǎn)化我們的代碼。

//?正確示例
for?(final?person?in?people)?{
??...
}

//?錯(cuò)誤示例
people.forEach((person)?{
??...
});

但是如果我們是要對(duì)每個(gè)元素進(jìn)行操作的話,那么可以直接將這個(gè)操作作為方法傳遞到 forEacth 中,這樣的代碼更簡(jiǎn)潔。

people.forEach(print);

注意 Map 是不可迭代的,因此使用 forEach 是沒問題的。

不要使用 List.from(),除非你想要更改結(jié)果的類型

下面是兩行對(duì)比的代碼:

var?list?=?['a',?'b'];

var?copy1?=?list.toList();
var?copy2?=?List.from(list);

print(copy1.runtimeType);
print(copy2.runtimeType);

猜猜打印出來的結(jié)果會(huì)是什么?

List<String>
List<dynamic>

如果使用 List.from 方法的話,如果不指定泛型類型,會(huì)抹除集合的類型,變成 dynamic?。。∫虼?,除非某些對(duì)象需要做這樣的類型轉(zhuǎn)換,否則不應(yīng)該使用 List.from 方法。當(dāng)然,List.from 也不是沒有用,比如數(shù)值類型支持強(qiáng)制轉(zhuǎn)換,可以指定類型做強(qiáng)制轉(zhuǎn)換,例如下面剩下的因?yàn)槎际钦麛?shù)了,因此可以轉(zhuǎn)為 List類型``。

var?numbers?=?[1,?2.3,?4];?//?List<num>.
numbers.removeAt(1);?//?Now?it?only?contains?integers.
var?ints?=?List<int>.from(numbers);

使用 whereType 過濾類型

如果要從動(dòng)態(tài)集合篩選某個(gè)類型的子集,那么應(yīng)該使用 whereType<T>方法,而不是使用 where 來過濾。

var?list?=?['1',?'2',?1,?2];

//?正確示例
var?intList?=?list.whereType<int>();

//?錯(cuò)誤示例
var?intList?=?list.where((e)?=>?e?is?int);

這是因?yàn)椋?code>where 方法返回的仍然是一個(gè) WhereIterable<Object>對(duì)象,而不是我們想要的WhereIterable<int> 對(duì)象,這意味如果使用 where 還需要做一次強(qiáng)制轉(zhuǎn)換,這并不推薦。

//?錯(cuò)誤示例
var?list?=?['1',?'2',?1,?2];
var?intList?=?list.where((e)?=>?e?is?int).cast<int>();

如果有別的方式的話,不要使用 cast 做強(qiáng)制轉(zhuǎn)換

通常,當(dāng)在處理迭代對(duì)象或 stream 的時(shí)候,我們會(huì)對(duì)其做一系列的操作。之后,我們會(huì)指定一個(gè)類型的對(duì)象。相對(duì)于使用 cast() 方法,我們應(yīng)該使用其他可能存在的轉(zhuǎn)換方式。例如,當(dāng)我們使用 toList 的時(shí)候,可以使用 List<T>.from 來進(jìn)行類型轉(zhuǎn)換。

//?正確示例
var?stuff?=?<dynamic>[1,?2];
var?ints?=?List<int>.from(stuff);

//?錯(cuò)誤示例
var?stuff?=?<dynamic>[1,?2];
var?ints?=?stuff.toList().cast<int>();

我們也可以使用 map<T> 來將集合轉(zhuǎn)為另一個(gè)類型的集合。

//?正確示例
var?stuff?=?<dynamic>[1,?2];
var?reciprocals?=?stuff.map<double>((n)?=>?1?/?n);

//?錯(cuò)誤示例
var?stuff?=?<dynamic>[1,?2];
var?reciprocals?=?stuff.map((n)?=>?1?/?n).cast<double>();

避免使用 cast() 做強(qiáng)制轉(zhuǎn)換

當(dāng)我們沒有其他辦法進(jìn)行類型轉(zhuǎn)換時(shí),那么也需要盡可能地避免使用 cast() 做類型轉(zhuǎn)換。這里有幾條建議能夠避免使用強(qiáng)制轉(zhuǎn)換:

正確地定義集合類型,如果集合類型是明確的,那么就應(yīng)該在集合對(duì)象定義時(shí)明確類型。例如下面的例子:

//?正確示例
List<int>?singletonList(int?value)?{
??var?list?=?<int>[];
??list.add(value);
??return?list;
}

//?錯(cuò)誤示例
List<int>?singletonList(int?value)?{
??var?list?=?[];?//?List<dynamic>.
??list.add(value);
??return?list.cast<int>();
}

在訪問元素時(shí)進(jìn)行轉(zhuǎn)換,當(dāng)進(jìn)行集合迭代的時(shí)候,可以在迭代過程中對(duì)每個(gè)元素進(jìn)行類型轉(zhuǎn)換。

//?正確示例
void?printEvens(List<Object>?objects)?{
??//?假設(shè)我們知道集合只有整數(shù)
??for?(final?n?in?objects)?{
????if?((n?as?int).isEven)?print(n);
??}
}

//?錯(cuò)誤示例
void?printEvens(List<Object>?objects)?{
??//?假設(shè)我們知道集合只有整數(shù)
??for?(final?n?in?objects.cast<int>())?{
????if?(n.isEven)?print(n);
??}
}

優(yōu)先使用 List.from() 做轉(zhuǎn)換。如果集合的大部分元素都會(huì)被訪問到,而且不再需要對(duì)轉(zhuǎn)換前的做處理,那么就使用 List.from 來做轉(zhuǎn)換。cast()方法返回的是一個(gè)延遲處理的集合,當(dāng)需要使用元素時(shí)才會(huì)執(zhí)行轉(zhuǎn)換。對(duì)于轉(zhuǎn)換少量元素而言,這樣效率會(huì)高。但是,大部分情況下,將對(duì)象包裝為延遲對(duì)象的缺陷更明顯。

//?正確示例
int?median(List<Object>?objects)?{
??//?假設(shè)我們知道集合只有整數(shù)
??var?ints?=?List<int>.from(objects);
??ints.sort();
??return?ints[ints.length?~/?2];
}

//??錯(cuò)誤示例
int?median(List<Object>?objects)?{
??//?假設(shè)我們知道集合只有整數(shù)
??var?ints?=?objects.cast<int>();
??ints.sort();
??return?ints[ints.length?~/?2];
}

總結(jié)

本篇總結(jié)了 Dart 語言中使用集合的一些場(chǎng)景的最佳實(shí)踐,實(shí)際上很多要點(diǎn)我們?cè)谄綍r(shí)并不會(huì)注意 —— 抱著能用就行了的態(tài)度。但是,這些內(nèi)容官方早就有了指引,知道何為正確會(huì)有助于我們編寫質(zhì)量更高的代碼!

以上就是詳解Flutter中Dart集合使用教程的詳細(xì)內(nèi)容,更多關(guān)于Flutter Dart集合的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論