Object.hash în Dart

Combină codurile hash ale mai multor valori într-unul singur; hashAll face același lucru pentru o colecție.

Sintaxă
static int hash(Object? object1, Object? object2, [Object? object3, ... Object? object20])
static int hashAll(Iterable<Object?> objects)

Ce face Object.hash

Când suprascrii hashCode, trebuie să combini codurile câmpurilor folosite în ==. Object.hash(a, b, c) face asta corect, pentru 2 până la 20 de valori. Ordinea contează: Object.hash(1, 2) și Object.hash(2, 1) dau de regulă valori diferite.

Object.hashAll(lista) combină codurile tuturor elementelor unei colecții, în ordine. Îl folosești când câmpul este o listă și egalitatea compară elementele. Pentru colecții în care ordinea nu contează (seturi) există Object.hashAllUnordered.

Rezultatul poate fi diferit între rulări (algoritmul folosește o valoare aleatoare la pornire), dar este constant pe durata unui program. Este tot ce contează pentru Set și Map.

Parametri

Parametru Descriere
object1 ... object20 Valorile combinate (pot fi null).
objects La hashAll: colecția de valori.

Ce returnează

Un int.

Exemple

Exemplul 1: O clasă folosită ca cheie în Map

class Adresa {
  final String oras;
  final String strada;
  final int numar;
  const Adresa(this.oras, this.strada, this.numar);

  @override
  bool operator ==(Object other) =>
      other is Adresa && other.oras == oras && other.strada == strada && other.numar == numar;

  @override
  int get hashCode => Object.hash(oras, strada, numar);
}

void main() {
  var livrari = <Adresa, int>{};
  livrari[Adresa('Iași', 'Lăpușneanu', 12)] = 2;
  livrari[Adresa('Cluj', 'Memorandumului', 1)] = 1;
  var cautata = Adresa('Iași', 'Lăpușneanu', 12);
  print(livrari[cautata]);
  print(livrari.containsKey(Adresa('Iași', 'Lăpușneanu', 13)));
}

Rezultat

2
false

Exemplul 2: hashAll pentru un câmp listă

class Comanda {
  final String client;
  final List<String> produse;
  Comanda(this.client, this.produse);

  @override
  bool operator ==(Object other) {
    if (other is! Comanda || other.client != client || other.produse.length != produse.length) {
      return false;
    }
    for (var i = 0; i < produse.length; i++) {
      if (other.produse[i] != produse[i]) return false;
    }
    return true;
  }

  @override
  int get hashCode => Object.hash(client, Object.hashAll(produse));
}

void main() {
  var a = Comanda('Ana', ['pâine', 'lapte']);
  var b = Comanda('Ana', ['pâine', 'lapte']);
  var c = Comanda('Ana', ['lapte', 'pâine']);
  print(a == b);
  print(a.hashCode == b.hashCode);
  print(a == c);
  print({a, b, c}.length);
  print(Object.hashAll([1, 2]) == Object.hashAll([1, 2]));
}

Rezultat

true
true
false
2
true

Greșeli frecvente

  • Combini codurile cu a.hashCode + b.hashCode sau ^. Merge, dar dă multe coliziuni (de exemplu (1, 2) și (2, 1) au același cod). Object.hash le distribuie mai bine.
  • Apelezi Object.hash(lista) pentru o listă: folosește identitatea listei, nu elementele. Folosește Object.hashAll(lista).

Comenzi înrudite

  • Object.hashCode: Un număr asociat obiectului, folosit de Set și Map; obiectele egale cu == trebuie să aibă același hashCode.
  • identical: Verifică dacă două variabile arată spre exact același obiect din memorie, nu doar spre obiecte egale.
  • Object: Clasa de bază a tuturor claselor Dart, cu excepția lui Null; runtimeType dă tipul real al unui obiect.