2D坐标的良好哈希码函数

时间:2014-04-03 01:44:39

标签: java hash hashmap hashcode

我想使用HashMap 将(x,y)坐标映射到值。 什么是好的hashCode()函数定义? 在这种情况下,我只存储形式(x,y)的整数坐标 其中y - x = 0,1,...,M - 1用于某些参数M。

5 个答案:

答案 0 :(得分:3)

要从两个数字中获取唯一值,您可以使用here中描述的双射算法 < X; y> = x +(y +(((x +1)/ 2)*((x +1)/ 2)))

这将为您提供unquie值,可用于哈希码

public int hashCode()
{
      int tmp = ( y +  ((x+1)/2));
               return x +  ( tmp * tmp);
}

答案 1 :(得分:1)

要计算具有多个属性的对象的哈希码,通常会实现通用解决方案。此实现使用常量因子来组合属性,因子的值是discussions的主题。似乎33或397因子通常会导致散列码的良好分布,因此它们适用于字典。

这是C#中的一个小例子,虽然它应该很容易适用于Java:

public override int GetHashCode()
{
  unchecked // integer overflows are accepted here
  {
    int hashCode = 0;
    hashCode = (hashCode * 397) ^ this.Hue.GetHashCode();
    hashCode = (hashCode * 397) ^ this.Saturation.GetHashCode();
    hashCode = (hashCode * 397) ^ this.Luminance.GetHashCode();
    return hashCode;
  }
}

此方案也适用于您的坐标,只需使用X和Y值替换属性即可。请注意,我们应该防止整数溢出异常,在DotNet中这可以通过使用unchecked块来实现。

答案 2 :(得分:1)

您是否考虑过将x或y移动一半的可用位?

对于“经典”8位,只有16个单元/轴,但今天的“标准”32位,它增长到65k以上的单元/轴。

@override
public int hashCode() {
    return x | (y << 15);
}

由于显而易见的原因,只有x和y都介于0和0xFFFF(0-65535,包括0和655)之间,这才有效,但是这个空间足够大,超过4.2bio单元格。

编辑: 另一种选择,但要求你知道实际尺寸,就是做x + y *宽度(其中宽度为x的方向为x)

答案 3 :(得分:1)

我通常使用Objects.hash(Object... value)为一系列项目生成哈希码。

  

生成哈希码就像将所有输入值都放在一个数组中一样,然后通过调用Arrays.hashCode(Object [])对那个数组进行哈希处理。

@Override
public int hashCode() {
    return Objects.hash(x, y);
}

Objects.hash(x, y, z)用于3D坐标。

如果您希望手动处理它,则可以使用以下方法计算hashCode:-

// For 2D coordinates
hashCode = LARGE_PRIME * X + Y;

// For 3D coordinates
hashCode = LARGE_PRIME^2 * X + LARGE_PRIME * Y + Z;

答案 4 :(得分:0)

这取决于您打算将哈希码用于:

如果您打算将其用作一种索引,例如知道 x 和 y 将散列到存储 (x, y) 数据的索引中,最好使用向量来处理这种事情。

Coordinates[][] coordinatesBucket = new Coordinates[maxY][maxX];

但是,如果您绝对必须为每个 (x, y) 组合提供唯一的哈希值,那么请尝试将坐标应用于十进制表(而不是相加或相乘)。例如,x=20 y=40 将为您提供简单且唯一的代码 xy=2040。