What's a good recipe for overriding hashcode i

2020-05-30 11:16发布

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?

标签: dart hashcode
5条回答
Luminary・发光体
2楼-- · 2020-05-30 11:38

I recomend "equatable" plugin

https://pub.dev/packages/equatable

Example:

Raw mode:

class Person {
  final String name;

  const Person(this.name);

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

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

With equatable :

import 'package:equatable/equatable.dart';

class Person extends Equatable {
  final String name;

  Person(this.name);

  @override
  List<Object> get props => [name];
}
查看更多
霸刀☆藐视天下
3楼-- · 2020-05-30 11:44

The equatable package can help

import 'package:equatable/equatable.dart';

class Person extends Equatable {
  final String name;
  final int age;

  Person(this.name, this.age);

  @override
  List<Object> get props => [name, age];
}

Now Person will use == and hashCode from Equatable, which takes props list that you give

查看更多
神经病院院长
4楼-- · 2020-05-30 11:46

While it's not a great answer, there is an open bug for providing this at https://code.google.com/p/dart/issues/detail?id=11617 and the "Jenkins SMI hash" referenced there seems like it would be the best thing to use if it were made publicly available.

查看更多
家丑人穷心不美
5楼-- · 2020-05-30 11:49

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.

查看更多
三岁会撩人
6楼-- · 2020-05-30 11:58

Since Dart is so similar to Java, you can surely find good references on hashCodes for Java that are applicable for Dart too.

A little googling took me to the Wikipedia page on Java's Object.hashCode(). Has a very basic example for the hashcode of a simple object. A popular methodology is to perform a multiplication with a prime number (different ones) and adding some value for each property of the object.

This question f.e. explains why the number 31 is chosen for multiplication for the String.hashCode() method.

More detailed examples of hashcode implementations can be easily found using Google.

查看更多
登录 后发表回答