Сегодня расскажу о сравнении коллекций и почему встроенный оператор == работает не так, как ожидают многие разработчики
Базовое сравнение
Встроенный оператор == у коллекций (List, Set, Map) проверяет ссылки на объект, а не содержимое. То есть два списка с одинаковыми элементами будут не равны, если это разные объекты в памяти:
void main() {
var a = [1, 2, 3];
var b = [1, 2, 3];
print(a == b); // false, разные объекты
print(identical(a, b)); // false
}Правильное сравнение содержимого
Для сравнения по значениям используют пакет collection. Он предоставляет специализированные классы для разных типов коллекций.
ListEquality
Сравнение списков поэлементно в строгом порядке:
import 'package:collection/collection.dart';
void main() {
var a = [1, 2, 3];
var b = [1, 2, 3];
print(const ListEquality().equals(a, b)); // true
}
SetEquality
Сравнение множеств без учета порядка элементов:
import 'package:collection/collection.dart';
void main() {
var a = {1, 2, 3};
var b = {3, 2, 1};
print(const SetEquality().equals(a, b)); // true
}
MapEquality
Сравнение словарей по ключам и значениям:
import 'package:collection/collection.dart';
void main() {
var a = {"x": 1, "y": 2};
var b = {"y": 2, "x": 1};
print(const MapEquality().equals(a, b)); // true
}
Глубокое сравнение
Если коллекции вложенные (List<Map<String, Set<int>>>), то используют DeepCollectionEquality. Он рекурсивно сравнивает элементы на любом уровне вложенности:
import 'package:collection/collection.dart';
void main() {
var a = [
{"nums": {1, 2}}
];
var b = [
{"nums": {2, 1}}
];
print(const DeepCollectionEquality().equals(a, b)); // true
}
Сравнение с кастомной логикой
Можно задать свою функцию сравнения для элементов коллекций:
import 'package:collection/collection.dart';
void main() {
var a = ["Hello", "world"];
var b = ["hello", "WORLD"];
var eq = ListEquality(StringEquality(ignoreCase: true));
print(eq.equals(a, b)); // true
}
❤️ — если было полезно