在Dart中重写hashcode的好方法是什么?

ebdffaop  于 11个月前  发布在  其他
关注(0)|答案(6)|浏览(131)

我发现自己想为一个对象覆盖hashcode和==,我想知道是否有最佳实践来实现依赖于多个属性的hashcode,似乎有一些Dart特定的考虑因素。
最简单的答案是对所有属性的哈希值进行异或,这可能不会太糟糕。

// 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;
 }

字符串
但这看起来像是它期望截断整数语义,而在Dart中,JS整数的范围溢出似乎不利于哈希。
我们也可以这样做,在每次操作后截断为32位。
对于我的应用程序来说,集合的预期大小非常小,几乎任何东西都可以,但我很惊讶没有看到一般情况下的标准配方。有人对此有任何经验或经验丰富吗?

du7egjpx

du7egjpx1#

quiver package提供了帮助函数hash2hash3等,这些帮助函数简化了hashCode的实现任务,并在一定程度上保证了hashCode在Dart VM * 和 * 下编译为JavaScript时能够正常工作。

import 'package:quiver/core.dart';

class Person {
  String name;
  int age;

  Person(this.name, this.age);

  @override
  bool operator ==(o) => o is Person && name == o.name && age == o.age;

  @override
  int get hashCode => hash2(name.hashCode, age.hashCode);
}

字符串
另请参阅this post以获得稍微详细的讨论。

jv2fixgn

jv2fixgn2#

从2.14版开始,Dart语言增加了对Object.hash()的支持,沿着还有Object.hashAll()Object.hashAllUnordered()
hash()文档:
为多个对象创建组合哈希代码。
范例:

class SomeObject {
  final Object a, b, c;
  SomeObject(this.a, this.b, this.c);

  bool operator==(Object other) =>
      other is SomeObject && a == other.a && b == other.b && c == other.c;

  int get hashCode => Object.hash(a, b, c); // <----- here
}

字符串
关于实施的文件说明:
此函数生成的哈希值不能保证在同一程序的不同运行中或在同一程序的不同隔离中运行的代码之间保持稳定。所使用的确切算法可能在不同平台之间或平台库的不同版本之间有所不同,并且可能取决于每次程序执行时更改的值。

2w3rbyxf

2w3rbyxf3#

为了最小化依赖关系,如果你已经依赖于flutter,但不依赖于像quiver这样的东西,dart:ui库包含用于创建和组合哈希值的工具,hashValueshashList。如果组合列表值,必须小心确保相等运算符和hashcode匹配行为。如果哈希代码深入计算它的哈希,然后使用深度相等,否则使用浅相等。

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

o2rvlv0m

o2rvlv0m4#

equatable软件包可以帮助

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];
}

字符串
现在Person将使用来自Equatable的==hashCode,Equatable接受您给予的props列表

atmip9wb

atmip9wb5#

我recomend“equatable”插件
https://pub.dev/packages/equatable
范例:
原始模式:

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;
}

字符串
equatable:

import 'package:equatable/equatable.dart';

class Person extends Equatable {
  final String name;

  Person(this.name);

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

ctrmrzij

ctrmrzij6#

由于Dart与Java非常相似,您肯定可以找到适用于Dart的Java hashCodes的好参考资料。
我在谷歌上搜索了一下Wikipedia page on Java's Object.hashCode()。它有一个简单对象的散列代码的非常基本的例子。一个流行的方法是用一个素数(不同的素数)执行乘法,并为对象的每个属性添加一些值。
This question f.e.解释了为什么选择数字31作为String.hashCode()方法的乘法。
更详细的hashcode实现的例子可以很容易地使用Google找到。

相关问题