Scala杂音哈希与Java本机哈希

Scala杂音哈希与Java本机哈希,java,scala,hash,Java,Scala,Hash,我正在学习scala,对case类的哈希代码部分有些困惑 就我所见,case类提供了toString、equals和hashCode的自动生成 在java中,传统观点认为java哈希代码使用本机实现 但在scala中,它使用 我的问题 1) Java有本机哈希代码,因为哈希代码依赖于机器,但是如果scala使用杂音哈希,那么它是如何独立于机器的呢 2) Scala有常规类和case类,普通类也使用杂音散列吗 3) 如果杂音散列确实是第1点之后最快的实现,那么为什么java仍然使用本机实现?杂音散

我正在学习scala,对case类的哈希代码部分有些困惑

就我所见,case类提供了toString、equals和hashCode的自动生成

在java中,传统观点认为java哈希代码使用本机实现

但在scala中,它使用

我的问题

1) Java有本机哈希代码,因为哈希代码依赖于机器,但是如果scala使用杂音哈希,那么它是如何独立于机器的呢

2) Scala有常规类和case类,普通类也使用杂音散列吗


3) 如果杂音散列确实是第1点之后最快的实现,那么为什么java仍然使用本机实现?

杂音散列是一种快速的高质量散列。Scala为它的集合、元组、case类和大多数其他库提供的对象(以及equals)提供了自动哈希代码,并且由于这些东西中的许多都在哈希映射中使用,所以拥有一个合适的默认哈希非常重要。哈什提供了这一点。据我所知,Java哈希也不依赖于机器,即使在某些情况下它们是用本机代码实现的。重要的是,每台机器的算法都是相同的,Scala的是因为它完全是用字节码实现的,Java的是因为任何不在字节码中的东西(我没有检查所有东西!)都是仔细做的

(至少对于任何扩展
java.util.AbstractList
的东西来说,传统的观点是错误的。它根本不是一个本机实现,只是迭代器上的一个循环,它调用内部的
hashCode
方法。但是JVM擅长这种循环和数学;为什么您希望它是本机的?)

Scala中的普通类不重写
hashCode
,因此它们不使用hash。但是,大多数不是case类的库类都使用杂音散列,例如,所有有序集合都使用杂音散列。(在顺序无关紧要的集合上使用顺序相关的杂音散列是不合适的。)

尽管杂音散列非常快,但它并不是最快的散列。Java通常使用
x(n)*31+x(n+1)
类型的算法进行散列,这会更快。不幸的是,这也是一个相当糟糕的杂烩。很容易发生碰撞。此外,杂音散列在低开销和整体速度快之间有一个很好的折衷,但是其他散列(例如XxHash或CityHash)对于大型对象可以更快,而代价是启动开销稍高一些。因此,并不是每个人都应该对每件事都使用杂音


尽管如此,之所以为Scala选择MurrullHash,是因为在更简单的典型Java风格的散列中存在明显的缺陷,而且它通常运行良好。为什么Java没有采用它?可能只是因为Java作为一种更为成熟的语言,其变化速度往往比Scala慢,而且还没有人能够理解它,和/或任何关心它的人已经在使用他们自己的自定义哈希解决方案。

如果我理解这一正确的Scala,请选择杂音哈希,因为它是最好的选择,但为什么普通scala类选择默认哈希?也许是因为兼容性?无法区分自定义散列和默认java散列默认散列不是散列,只是一个重新解释为散列代码的内存地址(就像在java中一样)。当你不知道一门课的哪些部分很重要时,这是非常明智的。定义equals和hashCode在某种意义上表达了您认为重要的内容。有两种“依赖于机器”:(1)代码是否在所有机器上执行?(2) 代码是否针对特定CPU进行了优化。Murrull有不同的版本,分别针对32位和64位以及little和big-endian进行优化。@ThomasFischer-Scala代码没有针对不同CPU的优化。无论如何,我们需要一个32位的散列,而且我们通常不能获取大块的字节,所以所有的大/小/64/32位的内容归结为一个默认实现。