Home > Software engineering >  Dart: why is a list or map not equal to [] and {} respectively
Dart: why is a list or map not equal to [] and {} respectively

Time:05-14

void main() {
  var a = [];
  var b = [];
  print(a == []);
  print(a == b);
  
  var c = ['c'];
  print(c == ['c']);
  
  var d = 'd';
  print(d == 'd');
}
false
false
false
true

This baffles me. Why is it like this?

Edit: I just realised it doesn't have to be empty

CodePudding user response:

It has to do with equality checks on Dart. They don't evaluate equality based on values, rather, they use hashCodes.

If you're using Dart in the context of Flutter you can use the native Flutter Method listEquals for value based comparison using Lists.

If you want value based equality on other Objects you must override the == operator or use packages like Equatable that helps you with that.

CodePudding user response:

The Dart platform libraries have chosen to, generally, not provide a native == implementation for mutable collections (or mutable objects in general).

Checking that [] == [] seems obvious, but they are different objects. If you do:

var l1 = [];
var l2 = [];
print(l1 == l2);
l1.add("an element");
print(l1 == l2);

do you expect the two ==s to give the same result? If not, how about:

var l1 = <int>[];
var l2 = <int>[];
var m = <List<int>>{l1}; // A set of lists.
print(m.contains(l2)); // true or false?
l1.add(1);
print(m.contains(l2)); // true or false?

On top of those concerns, which other languages also have, Dart have reified generics. An empty List<int> and an empty List<num> is not the same object, and runtime type-checks can tell the difference. Should <int>[] == <num>[] then? Definitely safest to say no!

All in all, Dart does not have == on List (or other collections) recursively check whether the two lists contain the same (or equal) elements. It only says true if it's the exact same object.

If you want to check list-element-equality, you can use the Equality classes from package:collection, like ListEquality and the custom hash/equals parameters to the hash map/set classes. Example:

const intListEquality = ListEquality<int>();
var listMap = LinkedHashMap<List<int>, String>(
    equals: intListEquality.equals, 
    hashCode: intListEquality.hash);
listMap[[1]] = "42";
print(listMap([1]); // 42
  • Related