← Назад к вопросам

С помощью каких методов добивается уникальность элементов в set?

1.7 Middle🔥 151 комментариев
#Архитектура Flutter#ООП и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Методы достижения уникальности элементов в Set

В Dart Set обеспечивает уникальность элементов через механизм хеширования и равенства (equality). Это один из ключевых аспектов работы с коллекциями в Dart.

Основной механизм: hashCode и equals

Для любого объекта в Dart существуют два критических метода:

class User {
  final int id;
  final String name;

  User(this.id, this.name);

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is User &&
          runtimeType == other.runtimeType &&
          id == other.id &&
          name == other.name;

  @override
  int get hashCode => id.hashCode ^ name.hashCode;
}

Как это работает:

  1. hashCode — возвращает целое число, которое служит "первичным ключом" для быстрого поиска
  2. operator == — проверяет точное равенство двух объектов
  3. Set сначала проверяет hashCode, затем если хеши совпадают, проверяет ==

Практический пример

final users = <User>{};

final user1 = User(1, Alice);
final user2 = User(1, Alice);
final user3 = User(2, Bob);

users.add(user1);
users.add(user2); // Не добавится, так как user1 == user2
users.add(user3); // Добавится

print(users.length); // 2

Встроенные типы

Для примитивных типов (int, String, bool) hashCode и operator == уже реализованы:

final numbers = {1, 2, 3, 2, 1};
print(numbers); // {1, 2, 3}

final strings = {flutter, dart, flutter};
print(strings.length); // 2

Проблемы и gotchas

❌ Неправильно:

class Product {
  final int id;
  Product(this.id);
  // Нет переопределения hashCode и operator ==
}

final p1 = Product(1);
final p2 = Product(1);

final set = {p1, p2};
print(set.length); // 2! Хотя логически они одинаковые

✅ Правильно:

class Product {
  final int id;
  Product(this.id);

  @override
  bool operator ==(Object other) =>
      other is Product && id == other.id;

  @override
  int get hashCode => id.hashCode;
}

final p1 = Product(1);
final p2 = Product(1);

final set = {p1, p2};
print(set.length); // 1

Оптимизация хеширования

Для сложных объектов используй Quiver или Equatable:

import package:equatable/equatable.dart;

class Order extends Equatable {
  final int id;
  final String customerName;
  final List<String> items;

  Order(this.id, this.customerName, this.items);

  @override
  List<Object?> get props => [id, customerName, items];
}

// Теперь hashCode и operator == генерируются автоматически
final order1 = Order(1, Alice, [item1]);
final order2 = Order(1, Alice, [item1]);

final orders = {order1, order2};
print(orders.length); // 1

LinkedHashSet для сохранения порядка

Обычный Set не гарантирует порядок элементов. Используй LinkedHashSet:

final set = LinkedHashSet<int>();
set.addAll([3, 1, 2, 1, 3]);
print(set); // {3, 1, 2}

Заключение

Уникальность в Set достигается через комбинацию:

  • hashCode для быстрого поиска коллизий
  • operator == для точной проверки равенства
  • Правильная реализация обоих методов в пользовательских классах

Всегда помни: если переопределяешь ==, то обязательно переопредели hashCode!