You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确重写含List的Dart类hashCode以保证相等实例哈希一致?

正确重写包含List成员的Dart类hashCode

你的问题核心在于:Dart中List的默认hashCode是基于对象身份(内存地址)而非内容的,所以即使两个列表元素完全相同,它们的hashCode也不一样。这就导致你用Object.hash(a, b)计算的Foo实例哈希值,会因为两个实例的a、b是不同的列表对象而产生差异,哪怕内容一致。

要解决这个问题,我们需要基于列表的内容来计算哈希值,而非列表对象本身。以下是两种无需第三方包的实现方式:

方法一:使用Object.hashAll直接计算列表内容哈希

Object.hashAll可以接收一个可迭代对象,基于其中所有元素的哈希值生成一个组合哈希,完美适配列表内容的哈希计算:

class Foo {
  final List<int> a;
  final List<int> b;
  Foo(this.a, this.b);

  @override
  bool operator ==(Object other) => 
      identical(this, other) || 
      other is Foo && 
      _listEquals(a, other.a) && 
      _listEquals(b, other.b);

  @override
  int get hashCode => Object.hash(Object.hashAll(a), Object.hashAll(b));

  // 自行实现列表相等判断,避免依赖第三方包
  bool _listEquals(List<int> a, List<int> b) {
    if (a.length != b.length) return false;
    for (int i = 0; i < a.length; i++) {
      if (a[i] != b[i]) return false;
    }
    return true;
  }
}

或者更简洁的写法,把两个列表的元素合并后计算哈希:

@override
int get hashCode => Object.hashAll([...a, ...b]);

注意:如果列表元素数量很大,展开列表会有轻微性能损耗,此时更推荐第一种分开计算的方式。

方法二:手动实现列表内容哈希计算

如果你想完全自定义哈希计算逻辑,可以写一个辅助函数遍历列表元素累加哈希:

class Foo {
  final List<int> a;
  final List<int> b;
  Foo(this.a, this.b);

  @override
  bool operator ==(Object other) => 
      identical(this, other) || 
      other is Foo && 
      _listEquals(a, other.a) && 
      _listEquals(b, other.b);

  // 辅助函数:计算List<int>的内容哈希
  int _calculateListHashCode(List<int> list) {
    int hash = 17; // 初始质数,减少哈希碰撞概率
    for (int num in list) {
      hash = 31 * hash + num.hashCode; // 31是常用的质数乘数,平衡性能和碰撞率
    }
    return hash;
  }

  @override
  int get hashCode => Object.hash(_calculateListHashCode(a), _calculateListHashCode(b));

  // 自行实现列表相等判断
  bool _listEquals(List<int> a, List<int> b) {
    if (a.length != b.length) return false;
    for (int i = 0; i < a.length; i++) {
      if (a[i] != b[i]) return false;
    }
    return true;
  }
}

验证效果

修改后运行你的测试代码:

final list1 = Foo([0], [0]);
final list2 = Foo([0], [0]);

print(list1 == list2); // 输出true
print(list1.hashCode == list2.hashCode); // 输出true

就能得到符合预期的结果。

内容的提问来源于stack exchange,提问作者iDecode

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 23:26:06