2

in Dart Documentation we have three iterable options to choose from to create lists .which one is best suited for what purpose and which is more effiecient for what purpose?

rushikesh chaskar
  • 642
  • 1
  • 7
  • 12
  • 2
    Does this answer your question? [In Dart, what's the difference between List.from and .of, and between Map.from and .of?](https://stackoverflow.com/questions/50320220/in-dart-whats-the-difference-between-list-from-and-of-and-between-map-from-a) `List.generate` is quite different from either `List.of`/`List.from`; it's used to construct a `List` from dynamically generated elements, not to copy an existing `Iterable`. – jamesdlin May 01 '20 at 05:11

2 Answers2

11

Basically, you should never use any of those constructors.

Each has its use, but most of those uses can be written using list literals now.

The List.generate is a counterpart to List.filled. The latter creates a list filled with the same value in each slot, the former allows you to compute a new value for each slot. With collection-for, I'd probably write:

 var newList = [for (var i = 0; i < 10; i++) compute(i)];

instead of

 var newList = List.generate(10, compute);

(even more so if I can inline the compute function). The one case where generate makes sense is to create a fixed-length list. The literal cannot do that.

I'd also say that you should never use List.of(something). Use something.toList() or [...something] instead. If you need to up-cast, say create a List<num> from an Iterable<int>, you can do <num>[...something], but you can't use toList. If you need to make a fixed-length List<num>, ... then I think List<num>.of(something, growable: false) is actually the simplest solution.

The only reason to use List.from is when the original iterable does not have as tight a type as needed. If you know that your Iterable<num> contains only integers, you might want to do List<int>.from(iterable). You can also do iterable.cast<int>().toList() or [for (var v in iterable) v as int], but List.from can be shorter. Always provide a type variable to List.from.

So, in general: Only use one of these constructors if you need a fixed-length list (passing growable: false), or if you want to down-cast the elements using List.from, and then always provide the type argument.

Otherwise use list literals. That's probably going to be more efficient too because it avoids some function calls.

lrn
  • 64,680
  • 7
  • 105
  • 121
  • 1
    As an update, `List.generate` would now be the fastest approach for null-safe list generation, starting from Dart 2.9. https://github.com/dart-lang/sdk/issues/42283#issuecomment-646167104 – First_Strike Oct 11 '20 at 18:28
  • I think you told me the meaning of "pendant" in one of your other answers to me, but I can't find it now. What is it that you mean by *"`List.generate` is a pendant to `List.filled`"*? – Suragch Aug 26 '21 at 08:44
  • Since you can also create a fixed-length list with `something.toList(growable: false)`, is there still any need to use something like `List.of(something, growable: false)`? Or are they equivalent? – Suragch Aug 26 '21 at 08:51
  • If you wish to create a `List` from a `List` (in order to add further doubles to the list later), then you need to use `List.from(intList)`. The `intList.toList()` can only create a new `List`. Otherwise the two are basically equivalent. The `.toList()` has a chance to be slightly more efficient since it knows (or can know) the implementation of the list it works on, where as `List.of` just knows it's some `Iterable`, and it has some overhead just from trying to detect cases where it can be more efficient (like checking whether `length` is efficient). – lrn Aug 26 '21 at 09:54
  • `List.toList(...)` implementation uses `List.of()` constructor, may I know where that efficiency comes from? – CopsOnRoad Dec 21 '21 at 07:27
  • There is no `List.toList` method implementation because `List` is an abstract interface. The `ListBase`/`ListMixin` implementations cannot assume anything except the object being a list. Other `List` implementations can *potentially* know more about themselves. In practice, few needs to because lists are such wonderfully simple data structures. If Dart had something more complicated, say like Java's [`ArrayList`](https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html), that would probably be able to take advantage of a more specialized `toList` implementation. – lrn Dec 21 '21 at 10:43
  • I think I couldn't frame my sentence clearly. I know that there's no implementation of `toList` in `List`, I was talking about [this toList](https://api.dart.dev/stable/2.14.4/dart-core/Iterable/toList.html). So, the question was if `Iterable.toList` is actually invoking `List.of`, then why don't we directly use `List.of(...)`, why there would be a performance difference? – CopsOnRoad Dec 21 '21 at 20:48
1

List.generate - This is useful if the source of your list is either not of type List or if you need a special logic when you retrieve list elements;

List.of - Type checking is done at compile time.

List.from - Type checking is only done during runtime.

Both List.of and List.from work the same. But you should prefer List.of over List.from to ensure type checking is performed as early as compile time.

If you want to look more closely, take a look at this example: https://dartpad.dev/b9cd4acdeec266cb366155c6ec40b4f1

kbaylosis
  • 308
  • 2
  • 9