Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's a good recipe for overriding hashcode in Dart?

Tags:

hashcode

dart

I find myself wanting to override hashcode and == for an object, and I'm wondering if there are best practices for how to implement a hashcode that depends on multiple attributes, and it seems like there are some Dart-specific considerations.

The simplest answer would be to XOR the hashes of all the attributes together, and it's probably not too bad. There's also an example in Dart Up and Running at https://www.dartlang.org/docs/dart-up-and-running/contents/ch03.html

  // Override hashCode using strategy from Effective Java, Chapter 11.  int get hashCode {    int result = 17;    result = 37 * result + firstName.hashCode;    result = 37 * result + lastName.hashCode;    return result;  } 

but that seems like it expects truncating integer semantics and in Dart overflowing the range of JS integers seems bad for hashing.

We could also do that and just truncate to 32 bits after each operation.

For my application the expected size of the set is very small and almost anything would do, but I'm surprised not to see a standard recipe for the general case. Does anyone have any experience or strong experience with this?

like image 865
Alan Knight Avatar asked Dec 13 '13 23:12

Alan Knight


People also ask

Can we override hashCode ()?

You must override hashCode() in every class that overrides equals(). Failure to do so will result in a violation of the general contract for Object. hashCode(), which will prevent your class from functioning properly in conjunction with all hash-based collections, including HashMap, HashSet, and Hashtable.

Can we override a equals () and hashCode () method How?

if you override equals, you must override hashCode. hashCode must generate equal values for equal objects. equals and hashCode must depend on the same set of significant fields . You must use the same set of fields in both of these methods.


2 Answers

The quiver package provides helper functions hash2, hash3, etc., which simplify the task of implementing hashCode, with some assurance that it works properly under the Dart VM and when compiled to JavaScript.

import 'package:quiver/core.dart';  class Person {   String name;   int age;    Person(this.name, this.age);    bool operator ==(o) => o is Person && name == o.name && age == o.age;   int get hashCode => hash2(name.hashCode, age.hashCode); } 

Also see this post for a slightly lengthier discussion.

like image 149
Patrice Chalin Avatar answered Sep 27 '22 20:09

Patrice Chalin


In the interests of minimizing dependencies, if you are already depending on flutter, but not depending on something like quiver, the dart:ui library contains utilites, hashValues and hashList for creating and combining hash values. If combining list values, one must be careful to ensure the equality operator and hashcode match behaviour. If the hash code computes it's hash deeply, then use deep equality, else, use shallow equality.

class Example {     final String value1;     final Object value2;     final List<Object> deep;     final List<Object> shallow;      Example({this.value1, this.value2, this.deep, this.shallow});      @override     operator ==(o) =>         o is Example &&         o.value1 == value1 &&         o.value2 == value2 &&         listEquals(o.deep, deep) &&         o.shallow == shallow;      @override     int get hashCode => hashValues(value1, value2, hashList(deep), shallow); } 

Flutter API docs for hashValues

Flutter API docs for hashList

like image 25
Daniel Brotherston Avatar answered Sep 27 '22 21:09

Daniel Brotherston