高效的MurmurHash 算法实现

目录

前言:

MurmurHash 介绍

各语言版本Murmurhash算法实现

C# 版本的Murmurhash算法实现

c/c++版本Murmurhash算法实现

java版本Murmurhash算法实现 


前言:

对与C#或其他语言,我们有时需要计算hashCode或计算一串字符串、类的唯一值。我们知道不同的语言版本所计算方法不一,但是都有相应的性能问题。MurmurHash 对于唯一值的计算相对就快速很多。


MurmurHash 介绍

MurmurHash 是一种高性能的哈希算法,由 Austin Appleby 在 2008 年创建。它是一种非加密哈希算法,可以快速地计算出任意数据的哈希值。

MurmurHash 算法的特点是快速、高效、低碰撞、低冲突,适用于各种哈希表、哈希集合、哈希映射等数据结构。它的哈希值分布均匀,哈希冲突率低,能够更好地处理哈希碰撞和哈希冲突。

MurmurHash 算法的原理是将输入数据分成若干个块,每个块都使用不同的哈希函数计算出一个哈希值,然后将这些哈希值进行混合和运算,得到最终的哈希值。MurmurHash 算法使用了一些技巧来保证哈希值的均匀分布,例如使用了随机数种子、对哈希值进行了混淆等。

MurmurHash 算法有多个版本,包括 32 位和 64 位版本,也有多个变种,例如 MurmurHash3、MurmurHash2、MurmurHash1 等。MurmurHash 算法的实现语言包括 C++、Java、C#、Python 等。

总之,MurmurHash 算法是一种高效、低冲突、低碰撞的哈希算法,适用于各种哈希表、哈希集合、哈希映射等数据结构,是一个非常优秀的哈希算法。

MurmurHash 算法相比于 hashCode 算法有以下优点:

  1. 更好的哈希性能:MurmurHash 算法在哈希性能方面比 hashCode 算法更优秀,因为它能够快速地计算出任意数据的哈希值。MurmurHash 算法的哈希性能取决于数据的分布情况,但是在大多数情况下,它都能够提供比较好的哈希性能。

  2. 更低的哈希冲突率:MurmurHash 算法在哈希冲突率方面比 hashCode 算法更优秀,因为它能够更好地处理哈希冲突。MurmurHash 算法使用了一些技巧来减少哈希冲突,例如使用了两个不同的哈希函数、对哈希值进行了混淆等。

  3. 更好的分布性:MurmurHash 算法的哈希值在分布性方面比 hashCode 算法更优秀,因为它能够更好地处理数据的分布情况。MurmurHash 算法使用了一些技巧来保证哈希值的均匀分布,例如使用了随机数种子、对哈希值进行了混淆等。

  4. 更少的哈希碰撞:MurmurHash 算法在哈希碰撞方面比 hashCode 算法更优秀,因为它能够更好地处理哈希碰撞。MurmurHash 算法使用了一些技巧来减少哈希碰撞,例如使用了两个不同的哈希函数、对哈希值进行了混淆等。

综上所述,MurmurHash 算法相比于 hashCode 算法具有更好的哈希性能、更低的哈希冲突率、更好的分布性和更少的哈希碰撞。因此,在需要高效的哈希算法时,MurmurHash 算法是一个更好的选择。


各语言版本Murmurhash算法实现

C# 版本的Murmurhash算法实现

使用第三方库 MurmurHash.Net 实现 MurmurHash 算法的示例代码:

using MurmurHash;

byte[] data = Encoding.UTF8.GetBytes("hello world");
uint seed = 0;
uint hash = MurmurHash3.Hash32(data, seed);

在上面的代码中,我们使用 MurmurHash3.Hash32() 方法计算输入数据的哈希值。data 是输入数据的字节数组,seed 是一个种子值,hash 是计算出的哈希值。

如果您想自己实现 MurmurHash 算法,可以参考以下代码:

public static class MurmurHash {
    public static uint Hash32(byte[] data, uint seed) {
        const uint c1 = 0xcc9e2d51;
        const uint c2 = 0x1b873593;
        const uint r1 = 15;
        const uint r2 = 13;
        const uint m = 5;
        const uint n = 0xe6546b64;

        uint hash = seed;
        uint len = (uint)data.Length;
        int pos = 0;

        while (len >= 4) {
            uint k = BitConverter.ToUInt32(data, pos);

            k *= c1;
            k = (k << r1) | (k >> (32 - r1));
            k *= c2;

            hash ^= k;
            hash = (hash << r2) | (hash >> (32 - r2));
            hash = hash * m + n;

            len -= 4;
            pos += 4;
        }

        if (len > 0) {
            uint k = 0;

            for (int i = 0; i < len; i++) {
                k |= (uint)data[pos + i] << (8 * i);
            }

            k *= c1;
            k = (k << r1) | (k >> (32 - r1));
            k *= c2;

            hash ^= k;
        }

        hash ^= (uint)data.Length;
        hash ^= hash >> 16;
        hash *= 0x85ebca6b;
        hash ^= hash >> 13;
        hash *= 0xc2b2ae35;
        hash ^= hash >> 16;

        return hash;
    }
}

 在上面的代码中,我们实现了 MurmurHash 算法的 32 位版本。data 是输入数据的字节数组,seed 是一个种子值,hash 是计算出的哈希值。

c/c++版本Murmurhash算法实现

#include <cstdint>
#include <cstring>

uint32_t murmurhash(const void* key, int len, uint32_t seed) {
    const uint32_t c1 = 0xcc9e2d51;
    const uint32_t c2 = 0x1b873593;
    const uint32_t r1 = 15;
    const uint32_t r2 = 13;
    const uint32_t m = 5;
    const uint32_t n = 0xe6546b64;

    const uint8_t* data = (const uint8_t*)key;
    const int nblocks = len / 4;

    uint32_t hash = seed;

    for (int i = 0; i < nblocks; i++) {
        uint32_t k = *(uint32_t*)(data + i * 4);

        k *= c1;
        k = (k << r1) | (k >> (32 - r1));
        k *= c2;

        hash ^= k;
        hash = (hash << r2) | (hash >> (32 - r2));
        hash = hash * m + n;
    }

    const uint8_t* tail = (const uint8_t*)(data + nblocks * 4);
    uint32_t k = 0;

    switch (len & 3) {
        case 3:
            k ^= tail[2] << 16;
        case 2:
            k ^= tail[1] << 8;
        case 1:
            k ^= tail[0];
            k *= c1;
            k = (k << r1) | (k >> (32 - r1));
            k *= c2;
            hash ^= k;
    }

    hash ^= len;
    hash ^= hash >> 16;
    hash *= 0x85ebca6b;
    hash ^= hash >> 13;
    hash *= 0xc2b2ae35;
    hash ^= hash >> 16;

    return hash;
}

 在上面的代码中,我们实现了 MurmurHash 算法的 32 位版本。key 是输入数据的指针,len 是输入数据的长度,seed 是一个种子值,hash 是计算出的哈希值。

java版本Murmurhash算法实现 

在 Java 中,我们可以使用 Guava 库或自己实现 MurmurHash 算法。

以下是一个使用 Guava 库实现 MurmurHash 算法的示例代码:

import com.google.common.hash.Hashing;

byte[] data = "hello world".getBytes();
int seed = 0;
int hash = Hashing.murmur3_32(seed).hashBytes(data).asInt();

在上面的代码中,我们使用 Hashing.murmur3_32() 方法创建一个 MurmurHash 算法的实例,然后使用 hashBytes() 方法计算输入数据的哈希值。data 是输入数据的字节数组,seed 是一个种子值,hash 是计算出的哈希值。 

如果您想自己实现 MurmurHash 算法,可以参考以下代码:

public static int murmurhash(byte[] data, int seed) {
    final int c1 = 0xcc9e2d51;
    final int c2 = 0x1b873593;
    final int r1 = 15;
    final int r2 = 13;
    final int m = 5;
    final int n = 0xe6546b64;

    int hash = seed;
    int len = data.length;
    int pos = 0;

    while (len >= 4) {
        int k = (data[pos] & 0xff) | ((data[pos + 1] & 0xff) << 8) | ((data[pos + 2] & 0xff) << 16) | ((data[pos + 3] & 0xff) << 24);

        k *= c1;
        k = (k << r1) | (k >>> (32 - r1));
        k *= c2;

        hash ^= k;
        hash = (hash << r2) | (hash >>> (32 - r2));
        hash = hash * m + n;

        len -= 4;
        pos += 4;
    }

    if (len > 0) {
        int k = 0;

        for (int i = 0; i < len; i++) {
            k |= (data[pos + i] & 0xff) << (8 * i);
        }

        k *= c1;
        k = (k << r1) | (k >>> (32 - r1));
        k *= c2;

        hash ^= k;
    }

    hash ^= data.length;
    hash ^= hash >>> 16;
    hash *= 0x85ebca6b;
    hash ^= hash >>> 13;
    hash *= 0xc2b2ae35;
    hash ^= hash >>> 16;

    return hash;
}

在上面的代码中,我们实现了 MurmurHash 算法的 32 位版本。data 是输入数据的字节数组,seed 是一个种子值,hash 是计算出的哈希值。 

猜你喜欢

转载自blog.csdn.net/lejian/article/details/131246251