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

詳解Flutter中Dart集合使用教程

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

前言

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

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

本篇介紹集合的最佳實踐。

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

對于核心的集合類ListMap 和 Set ,由于經常使用,Dart 為這些類提供的內置的語法來快速構建這些集合對象。

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

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

集合還有一些特殊的用法,比如使用展開操作符(而且同時支持 ? 操作符判斷是否為空)將一個集合加入到另一個集合。同時還支持結合 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')));

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

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

由于集合遵循的是 Iterable 協(xié)議,這個協(xié)議并不需要集合隨時知道它的長度。因此調用.length 的時候,其實相當于是遍歷了一遍,執(zhí)行速度是很低的。這是獲取 length 的實現(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('?');

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

避免使用 forEach 迭代元素

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

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

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

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

people.forEach(print);

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

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

下面是兩行對比的代碼:

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

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

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

猜猜打印出來的結果會是什么?

List<String>
List<dynamic>

如果使用 List.from 方法的話,如果不指定泛型類型,會抹除集合的類型,變成 dynamic?。?!因此,除非某些對象需要做這樣的類型轉換,否則不應該使用 List.from 方法。當然,List.from 也不是沒有用,比如數(shù)值類型支持強制轉換,可以指定類型做強制轉換,例如下面剩下的因為都是整數(shù)了,因此可以轉為 List類型``。

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

使用 whereType 過濾類型

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

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

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

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

這是因為,where 方法返回的仍然是一個 WhereIterable<Object>對象,而不是我們想要的WhereIterable<int> 對象,這意味如果使用 where 還需要做一次強制轉換,這并不推薦。

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

如果有別的方式的話,不要使用 cast 做強制轉換

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

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

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

我們也可以使用 map<T> 來將集合轉為另一個類型的集合。

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

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

避免使用 cast() 做強制轉換

當我們沒有其他辦法進行類型轉換時,那么也需要盡可能地避免使用 cast() 做類型轉換。這里有幾條建議能夠避免使用強制轉換:

正確地定義集合類型,如果集合類型是明確的,那么就應該在集合對象定義時明確類型。例如下面的例子:

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

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

在訪問元素時進行轉換,當進行集合迭代的時候,可以在迭代過程中對每個元素進行類型轉換。

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

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

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

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

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

總結

本篇總結了 Dart 語言中使用集合的一些場景的最佳實踐,實際上很多要點我們在平時并不會注意 —— 抱著能用就行了的態(tài)度。但是,這些內容官方早就有了指引,知道何為正確會有助于我們編寫質量更高的代碼!

以上就是詳解Flutter中Dart集合使用教程的詳細內容,更多關于Flutter Dart集合的資料請關注腳本之家其它相關文章!

相關文章

最新評論