关于Dart语言中hashCode的生成逻辑

简述

dart和其它面向对象的语言一样,对比两个对象是否相等的时候,都是依靠于HashCode的值来作对比的。
那么Dart中,hashCode的最原始值是怎么生成的呢?
直接看源码

   static final _hashCodeRnd = new Random();
  static int _objectHashCode(obj) {
    var result = _getHash(obj);//从缓存里获取
    if (result == 0) {
      // We want the hash to be a Smi value greater than 0.
      result = _hashCodeRnd.nextInt(0x40000000);
      do {
        result = _hashCodeRnd.nextInt(0x40000000);//
      } while (result == 0);
      _setHash(obj, result);//存入缓存
    }
    return result;
  }

逻辑非常简单清晰。就是生成一个随机数,然后将这个随机数缓存下来。当下次需要使用的时候,直接从缓存里取就好了。
这里可能很多人会有两个疑问:

1. 0x40000000是多大的数值?
2. 缓存存哪里?  

关于0x40000000

答案是2的31次方。

怎么算来的?

0x40000000是16进制,一个16进制对应的是4位2进制,所以40000000,对应的就是31位二进制。
关于二进制转10进制,这个就大家去百度吧。

那又为什么是31次方,不是32次方,30次方,或者其它数字呢。

因为int默认长度是32位,但是有一位是用来表示正负数的符号位。所以剩下31位用来表示数值的。
所以31位是int类型能表示的最大的2的n次幂的数值。
如果你很好奇为什么不用0X7FFFFFFF当最大值。为什么要选择2的n次幂,这和的hash值的计算有关系,具体做分析。

第二个问题,缓存存在哪儿呢?

@pragma("vm:recognized", "asm-intrinsic")
@pragma("vm:exact-result-type", "dart:core#_Smi")
int _getHash(obj) native "Object_getHash";
@pragma("vm:recognized", "asm-intrinsic")
void _setHash(obj, hash) native "Object_setHash";

// Helpers used to implement hashCode. If a hashCode is used, we remember it
// in a weak table in the VM (32 bit) or in the header of the object (64
// bit). A new hashCode value is calculated using a random number generator.

官方解释是在虚拟中缓存了一个32位弱引用表,将这些hashCode缓存在弱引用表里。
但是这个弱引用表有多大,满了之后如何替换的逻辑,就得看虚拟机里的实现逻辑了。

你可能感兴趣的:(flutter,dart,flutter)