什么';在Dart中重写哈希代码的好方法是什么?

什么';在Dart中重写哈希代码的好方法是什么?,dart,hashcode,Dart,Hashcode,我发现自己想要覆盖一个对象的hashcode和==,我想知道,对于如何实现依赖于多个属性的hashcode,是否有最佳实践,而且似乎有一些特定于Dart的注意事项 最简单的答案是将所有属性的散列异或在一起,这可能不是太糟糕。还有一个例子,在飞镖和运行在 //使用有效Java的策略覆盖哈希代码,第11章。 int获取哈希代码{ int结果=17; 结果=37*result+firstName.hashCode; 结果=37*result+lastName.hashCode; 返回结果; } 但这

我发现自己想要覆盖一个对象的hashcode和==,我想知道,对于如何实现依赖于多个属性的hashcode,是否有最佳实践,而且似乎有一些特定于Dart的注意事项

最简单的答案是将所有属性的散列异或在一起,这可能不是太糟糕。还有一个例子,在飞镖和运行在

//使用有效Java的策略覆盖哈希代码,第11章。
int获取哈希代码{
int结果=17;
结果=37*result+firstName.hashCode;
结果=37*result+lastName.hashCode;
返回结果;
}
但这似乎需要截断整数语义,而在Dart中溢出JS整数的范围似乎不利于散列

我们也可以这样做,每次操作后只需截断到32位


对于我的应用程序,集合的预期大小非常小,几乎任何东西都可以,但是我很惊讶没有看到一个适用于一般情况的标准配方。有人对此有经验吗?

由于Dart与Java非常相似,您肯定可以找到适用于Dart的Java哈希代码的好参考

我在谷歌上搜索了一下,就到了图书馆。有一个简单对象的hashcode的基本示例。一种流行的方法是使用质数(不同的质数)进行乘法,并为对象的每个属性添加一些值

f.e.解释了为什么选择数字31作为
String.hashCode()
方法的乘法

使用Google可以很容易地找到hashcode实现的更详细示例。

提供了帮助函数
hash2
hash3
,这些函数简化了实现
hashcode
的任务,并在一定程度上保证了它在Dart VM下以及编译为JavaScript时能够正常工作

导入“包:quiver/core.dart”; 班主任{ 字符串名; 智力年龄; 人(这个名字,这个年龄); 布尔运算符==(o)=>o是Person&&name==o.name&&age==o.age; int get hashCode=>hash2(name.hashCode,age.hashCode); } 另请参阅,以获得更为冗长的讨论。

该软件包可以提供帮助

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];
}
import'包:equalable/equalable.dart';
类Person扩展了equalable{
最后的字符串名;
最终积分;
人(这个名字,这个年龄);
@凌驾
列表获取道具=>[姓名、年龄];
}
现在,此人将使用Equatable中的
==
hashCode
,这将获得您提供的
道具列表

我推荐“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;
}
具有相等的:

import 'package:equatable/equatable.dart';

class Person extends Equatable {
  final String name;

  Person(this.name);

  @override
  List<Object> get props => [name];
}
import'包:equalable/equalable.dart';
类Person扩展了equalable{
最后的字符串名;
人员(姓名);
@凌驾
列表获取道具=>[name];
}

为了最小化依赖性,如果您已经依赖于flift,但不依赖于类似于
quiver
的东西,
dart:ui
库包含用于创建和组合散列值的实用程序、
hashValues
hashList
。如果组合列表值,必须小心确保相等运算符和哈希代码匹配行为。如果哈希代码计算其哈希深度,则使用深度相等,否则使用浅相等

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);
}
类示例{
最终字符串值1;
最终目标值2;
最后的名单很深;
最终名单;
示例({this.value1,this.value2,this.deep,this.shallow});
@凌驾
运算符==(o)=>
o是一个例子&&
o、 value1==value1&&
o、 value2==value2&&
ListQuals(o.deep,deep)&&
o、 浅==浅;
@凌驾
int get hashCode=>hashValues(值1、值2、hashList(深)、浅);
}


我说“菜谱”几乎是-1分,但既然你的问题质量很好,我就排第一。当然,你应该在标题中使用的术语是算法,甚至是“方法”(比如,好方法,或好算法),而不是“好食谱”。如果你觉得算法这个词听起来像是在炫耀,我可以理解。你可以说“way”,但下面使用“recipe”一词,也许可以从另一种语言中寻找具有任意精度整数的示例。我相信Smalltalk有这些,Dart的整数很有趣,因为它们在虚拟机上是任意的,但是如果你编译成JavaScript,你就会受到JavaScript的限制。所以你想要截断,有趣的问题是在哪里以及如何做到最好。这大概是移位/乘法、异或和截断的组合。这也是Smalltalk倾向于做的事情。魔鬼在于细节。我不知道Dart和Java有这么相似。特别是,它在处理整数类型方面有所不同,Java的公共哈希如果应用于大量事物,就会溢出到Javascript整数范围之外,这是不好的。Java ints溢出也是不好的。您可能希望使用dart:typed_数据包中的int32或int64,以便哈希代码保持一致。Javascript整数(以及编译为Javascript时的Dart整数)通过变为双精度溢出,这对于散列来说更糟糕。使用int32数据类型会有所帮助,但是dart:typed_数据没有单一的int类型,它只有集合。谢谢。这正是我要找的。记得添加quiver作为依赖项。在你的pubspec.yaml:
quiver:'>=0.18.0难道
hash2(姓名、年龄)
不够吗?添加
import'包:quiver/core.dart'
for
hash2()
不幸的是,当您使用提供程序时,这不适用于带有extends from ChangeNotifier的模型StateManagement@NiklasLehnfeld如果需要扩展另一个类,可以使用mixin。例如,
class MyModel使用equalableMixin扩展了ChangeNotifier