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

Dart开发能否以自定义对象作为Map键?为何按坐标取值返回null?

自定义类作为Map键取值返回null的问题说明

基本判定结论

自定义类可以直接作为Dart中Map的键使用,取值返回null是因为类没有实现正确的值相等判断规则。

问题根因

Dart的Map在做键匹配时,会按照固定流程校验:

  • 先比对两个键的hashCode值是否一致,哈希值不一致的对象会被直接判定为不同的键
  • 哈希值一致的前提下,再通过==运算符判断两个对象是否值相等
  • 两项校验全部通过,才会认定两个对象是同一个键

原有Coordinates类没有重写上述两个方法,完全沿用了Object基类的默认实现:默认==逻辑直接比对对象的内存引用地址,默认hashCode也是基于内存地址生成。这就导致哪怕两个Coordinates实例的col、row属性值完全相同,只要是独立创建的不同实例,在Map的校验逻辑里就属于完全不同的键,最终匹配失败返回null。

修正实现

要让属性值完全一致的Coordinates实例被判定为同一个键,必须在类定义中补充重写==运算符和hashCode属性,可选两种实现方式:

原生无依赖实现

直接使用Dart内置的工具方法完成逻辑,不需要引入第三方包:

class Coordinates {
  final int col;
  final int row;

  Coordinates(this.col, this.row);

  // 重写相等判断规则
  @override
  bool operator ==(Object? other) {
    return other is Coordinates 
      && other.col == col 
      && other.row == row;
  }

  // 重写哈希值计算规则
  @override
  int get hashCode => Object.hash(col, row);

  int getCol() => col;
  int getRow() => row;
}

其中Object.hash是Dart 2.19版本后内置的静态方法,可以直接组合多个字段的哈希值生成对象的哈希码,避免手动拼接计算的逻辑出错。

基于quiver工具包实现

如果项目已经引入quiver依赖,可以借助其提供的哈希工具简化代码:

import 'package:quiver/core.dart';

class Coordinates {
  final int col;
  final int row;

  Coordinates(this.col, this.row);

  @override
  bool operator ==(Object? o) => o is Coordinates && col == o.col && row == o.row;
  @override
  int get hashCode => hash2(col.hashCode, row.hashCode);

  int getCol() => col;
  int getRow() => row;
}

重要注意事项:重写==运算符时必须同步重写hashCode,只修改相等判断逻辑不修改哈希规则,依然会出现Map键匹配失败的问题——哈希值不一致的对象根本不会进入后续的相等判断环节。

内容的提问来源于stack exchange,提问作者Кадыр Атаханов

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.30 07:15:04