51

Every time I need to iterate over the values of a Map in Dart, I contemplate the cost that this loop will incur, in terms of the complexity and the amount of garbage produced. There are two ways to iterate over the values of a Map: Map.values, and Map.entries. For example:

Map<String, Person> people;

int olderThan(int age) {
  int result = 0;
  for(Person p in people.values)
    if(p.age > age) result++;
  return result;
}

int olderThan2(int age) {
  int result = 0;
  for(MapEntry<String, Person> me in people.entries)
    if(me.value.age > age) result++;
  return result;
}

// Which one is faster: olderThan or olderThan2?

If Map stores its values internally as MapEntry objects, it's possible that entries would be just as efficient or even more efficient than values. The implementation details of Map are buried deep inside Dart libraries, so I wonder if anybody has this knowledge and can shed the light on this subject.

I understand that Map.entries gives you access to the key, but I am talking about cases where I don't need to use the key of the entry. I also understand that there are different implementations of Map. I am mostly interested in the default implementation, LinkedHashMap, but if it would be nice to know if there's a difference between the different Map implementations in this aspect.

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
Alexander Ryzhov
  • 2,705
  • 3
  • 19
  • 19

2 Answers2

75

We should iterate map based on the requirement.

  1. If we required to iterate only keys

    map.keys.forEach((k) => print("Key : $k"));

  2. If we required to iterate only values

    map.values.forEach((v) => print("Value: $v"));

  3. If we required to iterate both key values.

    map.forEach((k, v) => print("Key : $k, Value : $v"));

Petro
  • 3,484
  • 3
  • 32
  • 59
Jitesh Mohite
  • 31,138
  • 12
  • 157
  • 147
22

If you iterate over entries a MapEntry instance is created for every key-value combination.

If you only need values, iterating map.values is more efficient.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • 3
    Also `MapEntry` contains `final` values, so you can't change them if you want to. – Michel Feinstein Jan 14 '20 at 04:22
  • So it is basically same to just forEach() except it is final then – dontknowhy Oct 11 '21 at 00:33
  • @PaemKacit I don't think that statement applies, but I'm not sure I understand what you mean. `forEach()` iterates over every collection and is not tied to Map. `entries` or `values` is just about how the `Map` provides a collection of its content. Iterating over that collection is a different step. – Günter Zöchbauer Oct 11 '21 at 09:36
  • hm.. map.forEach((k, v) => also iterates map\`s key and value but I guess you want to say "when it\`s only iterate inside one map variable" for(MapEntry me in people.entries) is more efficient right – dontknowhy Oct 11 '21 at 09:44
  • 1
    @PaemKacit I think I get now what you mean. `map.forEach()` works differently, it iterates all keys and all values for each key. So the difference is similar, as it passes key and value as-is, while `entries` creates a new instance of the `MapEntry` class, containing key and value for every key-value pair. – Günter Zöchbauer Oct 11 '21 at 10:16
  • Which is more efficient you think?? in performance – dontknowhy Oct 11 '21 at 12:22
  • 1
    @PaemKacit I'd expect omitting the `MapEntry` creation would be more efficient. First it needs to create these object instances, then later the garbage collector needs to dispose them. The iteration work over all keys and values needs to be done in any case. – Günter Zöchbauer Oct 11 '21 at 16:29