Introduction

There are four kinds of collections in dart, namely Set, List, Map and queues. What should we pay attention to when using these sets? What kind of use is the best way to use it? Let's take a look.

Use literals to create collections

For the three commonly used Set, Map and List collections, they have their own no-argument constructors:

  factory Set() = LinkedHashSet<E>;
  external factory Map();

  @Deprecated("Use a list literal, [], or the List.filled constructor instead")
  external factory List([int? length]);

You can see that Set and Map can use constructors. But for List, the parameterless constructor has been deprecated.

For Set and Map, it can be constructed like this:

var studentMap = Map<String, Student>();
var ages = Set<int>();

However, dart officially recommends using literals directly to create these collections, as follows:

var studentMap = <String, Student>{};
var ages = <int>{};

why? This is because literal collections in dart are very powerful. Collections can be constructed and expanded through the spread operator, if and for statements, as follows:

var studentList = [
  ...list1,
  student1,
  ...?list2,
  for (var name in list3)
    if (name.endsWith('jack'))
      name.replaceAll('jack', 'mark')
];

Don't use .length to tell if a collection is empty

For Dart's traversable collections, these collections do not store the length information of the collection, so if you call the .length method of the collection, it may cause the collection to be traversed, thereby affecting performance.

Note that Set and List are traversable, while Map is not.

Therefore, we need to call the .isEmpty and .isNotEmpty methods of the collection to determine whether the collection is empty, which is faster.

if (studentList.isEmpty) print('it is empty');
if (studentList.isNotEmpty) print('it is not empty');

Traversal of traversable objects

Corresponding to the two traversable collections Set and List, there are two traversal methods, which can be traversed by calling the forEach() method or for-in, as shown below:

for (final student in studentList) {
  ...
}
studentList.forEach((student) {
  ...
});

Of these two methods, dart recommends using the for in method.

Of course, forEach is also fine if you want to apply an existing function to each element in the collection:

studentList.forEach(print);
Note that the above rules do not apply to Maps because Maps are not traversable.

List.from and iterable.toList

Traversable objects can be converted into Lists by calling toList, and the same List.from can also convert traversable objects into Lists.

So what is the difference between the two?

var list1 = iterable.toList();
var list2 = List.from(iterable);

The difference between the two is that iterable.toList does not change the type of the data in the list, while List.from does. For example:

// Creates a List<String>:
var studentList = ['jack', 'mark', 'alen'];

// Prints "List<String>":
print(studentList.toList().runtimeType);

// Prints "List<dynamic>":
print(List.from(studentList).runtimeType);

Of course, you can also use List<T>.from to force the type conversion of the created List.

List<String>.from(studentList)

where and whereType

For traversable objects, there are two methods for filtering elements in a collection, they are where and whereType.

For example, if we need to filter the strings in the List, we can write:

var studentList = ['jack', 'ma', 18, 31];
var students1 = studentList.where((e) => e is String);
var students2 = studentList.whereType<String>();

It seems that there is not much difference between the two, and both can get the expected results. But there is actually a difference between the two, because for where, a Iterable<Object> is returned, so in the above example, if we really need to return String, we also need to case the returned result:

var students1 = studentList.where((e) => e is String).cast<String>();;

So, remember to use whereType if you want to return a specific object.

avoid using cast

Cast is usually used to perform type conversion operations on the elements in the collection, but the performance of cast is relatively low, so it must be avoided in the case of a last resort.

So how do we convert types without using cast?

A basic principle is to perform type conversion in advance when building the collection, rather than performing the overall cast after the collection is constructed.

For example, the following example converts a dynamic type List to an int type List, then we can perform the type conversion when calling the List.from method:

var stuff = <dynamic>[1, 2];
var ints = List<int>.from(stuff);

If it is a map, it can be done like this:

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

For example, if we need to build a List of ints, we can specify the internal type of the List at the beginning of creation, and then add elements to it:

List<int> singletonList(int value) {
  var list = <int>[];
  list.add(value);
  return list;
}

Summarize

These are the best practices for using collections in dart.

This article has been included in http://www.flydean.com/30-dart-collection/

The most popular interpretation, the most profound dry goods, the most concise tutorials, and many tricks you don't know are waiting for you to discover!

Welcome to pay attention to my official account: "Program those things", understand technology, understand you better!


flydean
890 声望433 粉丝

欢迎访问我的个人网站:www.flydean.com