Home > OS >  Dart initialise a list in a Map using putIfAbsent
Dart initialise a list in a Map using putIfAbsent

Time:10-11

I have a map of lists e.g.

HashMap exampleMap = new HashMap<String, List<Foo>>();

I want to initialise a new list if the key does not exist, I've been trying variations of putIfAbsent but have had no success so far

exampleMap.putIfAbsent('bar', () => []);

My ultimate goal is to add items to the list but the list needs to be initialised first

exampleMap['bar'].add(fooItem);

CodePudding user response:

There are a couple things wrong:

HashMap exampleMap = new HashMap<String, List<Foo>>();

This declares exampleMap to be a HashMap<dynamic, dynamic>. (See Why is dart wrongly inferring my generic parameter type? for an explanation why.)

The moral is: if you want to declare types explicitly, you must be explicit everywhere. You can't take half-measures. Otherwise just use var and allow the type of the variable to be inferred from the right-hand-side.

Later when you do:

exampleMap.putIfAbsent('bar', () => []);

Because exampleMap's static (known at compile-time) type is HashMap<dynamic, dynamic>, nothing is known about the type for the HashMap's values. The return type of the anonymous function (() => []) thus cannot be inferred, and since it returns an empty list with no explicit type parameter, the List's element type also cannot be inferred. The anonymous function therefore is compiled as a Function that returns a List<dynamic>.

Meanwhile, exampleMap's runtime type is actually a HashMap<String, List<Foo>>. When you execute the code, putIfAbsent will fail due to the inability to safely add a List<dynamic> where a List<Foo> is expected.

If you fix your original declaration to use var, then your putIfAbsent call should work without any additional changes. If you actually do want exampleMap's static type to be HashMap<dynamic, dynamic>, then you alternatively could change your putIfAbsent call to provide an explicit type for the empty List: exampleMap.putIfAbsent('bar', () => <Foo>[]).

I'll also point out that if you don't allow null values in your Map, I much prefer using ??= over putIfAbsent:

var exampleMap = HashMap<String, List<Foo>>();
exampleMap['bar'] ??= [];
  • Related