mysql fnv64函数_把string映射到64位的hashcode值方法

本文详细介绍了xMemcached中使用的多种哈希算法实现,包括原生哈希、CRC32、FNV系列、Ketama等算法,并提供了具体的Java源代码示例。

可以参考

xmemcached 的实现,源码如下:

public enum HashAlgorithm {

/**

* Native hash (String.hashCode()).

*/

NATIVE_HASH,

/**

* CRC32_HASH as used by the perl API. This will be more consistent both

* across multiple API users as well as java versions, but is mostly likely

* significantly slower.

*/

CRC32_HASH,

/**

* FNV hashes are designed to be fast while maintaining a low collision

* rate. The FNV speed allows one to quickly hash lots of data while

* maintaining a reasonable collision rate.

*

* @see http://www.isthe.com/chongo/tech/comp/fnv/

* @see http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash

*/

FNV1_64_HASH,

/**

* Variation of FNV.

*/

FNV1A_64_HASH,

/**

* 32-bit FNV1.

*/

FNV1_32_HASH,

/**

* 32-bit FNV1a.

*/

FNV1A_32_HASH,

/**

* MD5-based hash algorithm used by ketama.

*/

KETAMA_HASH,

/**

* From mysql source

*/

MYSQL_HASH,

ELF_HASH,

RS_HASH,

/**

* From lua source,it is used for long key

*/

LUA_HASH,

ELECTION_HASH,

/**

* The Jenkins One-at-a-time hash ,please see

* http://www.burtleburtle.net/bob/hash/doobs.html

*/

ONE_AT_A_TIME;

private static final long FNV_64_INIT = 0xcbf29ce484222325L;

private static final long FNV_64_PRIME = 0x100000001b3L;

private static final long FNV_32_INIT = 2166136261L;

private static final long FNV_32_PRIME = 16777619;

/**

* Compute the hash for the given key.

*

* @return a positive integer hash

*/

public long hash(final String k) {

long rv = 0;

switch (this) {

case NATIVE_HASH:

rv = k.hashCode();

break;

case CRC32_HASH:

// return (crc32(shift) >> 16) & 0x7fff;

CRC32 crc32 = new CRC32();

crc32.update(ByteUtils.getBytes(k));

rv = crc32.getValue() >> 16 & 0x7fff;

break;

case FNV1_64_HASH: {

// Thanks to pierre@demartines.com for the pointer

rv = FNV_64_INIT;

int len = k.length();

for (int i = 0; i < len; i++) {

rv *= FNV_64_PRIME;

rv ^= k.charAt(i);

}

}

break;

case FNV1A_64_HASH: {

rv = FNV_64_INIT;

int len = k.length();

for (int i = 0; i < len; i++) {

rv ^= k.charAt(i);

rv *= FNV_64_PRIME;

}

}

break;

case FNV1_32_HASH: {

rv = FNV_32_INIT;

int len = k.length();

for (int i = 0; i < len; i++) {

rv *= FNV_32_PRIME;

rv ^= k.charAt(i);

}

}

break;

case FNV1A_32_HASH: {

rv = FNV_32_INIT;

int len = k.length();

for (int i = 0; i < len; i++) {

rv ^= k.charAt(i);

rv *= FNV_32_PRIME;

}

}

break;

case ELECTION_HASH:

case KETAMA_HASH:

byte[] bKey = computeMd5(k);

rv = (long) (bKey[3] & 0xFF) << 24 | (long) (bKey[2] & 0xFF) << 16

| (long) (bKey[1] & 0xFF) << 8 | bKey[0] & 0xFF;

break;

case MYSQL_HASH:

int nr2 = 4;

for (int i = 0; i < k.length(); i++) {

rv ^= ((rv & 63) + nr2) * k.charAt(i) + (rv << 8);

nr2 += 3;

}

break;

case ELF_HASH:

long x = 0;

for (int i = 0; i < k.length(); i++) {

rv = (rv << 4) + k.charAt(i);

if ((x = rv & 0xF0000000L) != 0) {

rv ^= x >> 24;

rv &= ~x;

}

}

rv = rv & 0x7FFFFFFF;

break;

case RS_HASH:

long b = 378551;

long a = 63689;

for (int i = 0; i < k.length(); i++) {

rv = rv * a + k.charAt(i);

a *= b;

}

rv = rv & 0x7FFFFFFF;

break;

case LUA_HASH:

int step = (k.length() >> 5) + 1;

rv = k.length();

for (int len = k.length(); len >= step; len -= step) {

rv = rv ^ (rv << 5) + (rv >> 2) + k.charAt(len - 1);

}

case ONE_AT_A_TIME:

try {

int hash = 0;

for (byte bt : k.getBytes("utf-8")) {

hash += (bt & 0xFF);

hash += (hash << 10);

hash ^= (hash >>> 6);

}

hash += (hash << 3);

hash ^= (hash >>> 11);

hash += (hash << 15);

return hash;

} catch (UnsupportedEncodingException e) {

throw new IllegalStateException("Hash function error", e);

}

default:

assert false;

}

return rv & 0xffffffffL; /* Truncate to 32-bits */

}

/**

* Get the md5 of the given key.

*/

public static byte[] computeMd5(String k) {

MessageDigest md5;

try {

md5 = MessageDigest.getInstance("MD5");

} catch (NoSuchAlgorithmException e) {

throw new RuntimeException("MD5 not supported", e);

}

md5.reset();

md5.update(ByteUtils.getBytes(k));

return md5.digest();

}

// public static void main(String[] args) {

// HashAlgorithm alg=HashAlgorithm.CRC32_HASH;

// long h=0;

// long start=System.currentTimeMillis();

// for(int i=0;i<100000;i++)

// h=alg.hash("MYSQL_HASH");

// System.out.println(System.currentTimeMillis()-start);

// }

}

1

4

分享到:

18e900b8666ce6f233d25ec02f95ee59.png

72dd548719f0ace4d5f9bca64e1d7715.png

2012-08-21 16:59

浏览 3338

评论

我的字符串计算无论什么情况下都只计算了1次,如下函数,所以你优化的时候不能使用strlen之类重新计算字串unsigned int INI::String::calc_string(const char* _szText) { const char* szSource = _szText; //目标字串操作指针 unsigned int uiMagicBits = 0x7EFEFEFFL; //cpu进行运算所需的因子数,计算4byte里面是否含有空字符'0' unsigned int uiBlock; //抽出来的4byte配合MagicBits进行运算,快速判断4byte里面是否含有空字符'0' unsigned int uiLen = 0; unsigned int iFNVPrime = 16777619; //FNV质数 m_HashValue64.m_uiHash1 = 2166136261; //FNV1的基础 m_HashValue64.m_uiHash1a = 2166136261; //FNV1a的基础 while (true) { uiBlock = *(unsigned int*)szSource;//抽4byte出来 if ((((uiBlock + uiMagicBits) ^ ~uiBlock) & ~uiMagicBits) != 0)//计算4byte里面是否含有空字符'0' { //4byte里面有结束符 if (szSource[0] == '\0') { break;//第一已经是结束符 } else if (szSource[1] == '\0')//说明0是有效字符 { uiLen += 1; if (!is_space(szSource[0])) { //计算0FNV1 hash m_HashValue64.m_uiHash1 *= iFNVPrime; m_HashValue64.m_uiHash1 ^= szSource[0]; //计算0FNV1a hash m_HashValue64.m_uiHash1a ^= szSource[0]; m_HashValue64.m_uiHash1a *= iFNVPrime; } } else if (szSource[2] == '\0')//说明0和1是有效字符 { uiLen += 2; if (!is_space(szSource[0])) { //计算0FNV1 hash m_HashValue64.m_uiHash1 *= iFNVPrime; m_HashValue64.m_uiHash1 ^= szSource[0]; //计算0FNV1a hash m_HashValue64.m_uiHash1a ^= szSource[0]; m_HashValue64.m_uiHash1a *= iFNVPrime; } if (!is_space(szSource[1])) { //计算1FNV1 hash m_HashValue64.m_uiHash1 *= iFNVPrime; m_HashValue64.m_uiHash1 ^= szSource[1]; //计算1FNV1a hash m_HashValue64.m_uiHash1a ^= szSource[1]; m_HashValue64.m_uiHash1a *= iFNVPrime; } } else if (szSource[3] == '\0')//说明0,1,2是有效字符 { uiLen += 3; if (!is_space(szSource[0])) { //计算0FNV1 hash m_HashValue64.m_uiHash1 *= iFNVPrime; m_HashValue64.m_uiHash1 ^= szSource[0]; //计算0FNV1a hash m_HashValue64.m_uiHash1a ^= szSource[0]; m_HashValue64.m_uiHash1a *= iFNVPrime; } if (!is_space(szSource[1])) { //计算1FNV1 hash m_HashValue64.m_uiHash1 *= iFNVPrime; m_HashValue64.m_uiHash1 ^= szSource[1]; //计算1FNV1a hash m_HashValue64.m_uiHash1a ^= szSource[1]; m_HashValue64.m_uiHash1a *= iFNVPrime; } if (!is_space(szSource[2])) { //计算2FNV1 hash m_HashValue64.m_uiHash1 *= iFNVPrime; m_HashValue64.m_uiHash1 ^= szSource[2]; //计算2FNV1a hash m_HashValue64.m_uiHash1a ^= szSource[2]; m_HashValue64.m_uiHash1a *= iFNVPrime; } } break; } else { if (!is_space(szSource[0])) { //计算0FNV1 hash m_HashValue64.m_uiHash1 *= iFNVPrime; m_HashValue64.m_uiHash1 ^= szSource[0]; //计算0FNV1a hash m_HashValue64.m_uiHash1a ^= szSource[0]; m_HashValue64.m_uiHash1a *= iFNVPrime; } if (!is_space(szSource[1])) { //计算1FNV1 hash m_HashValue64.m_uiHash1 *= iFNVPrime; m_HashValue64.m_uiHash1 ^= szSource[1]; //计算1FNV1a hash m_HashValue64.m_uiHash1a ^= szSource[1]; m_HashValue64.m_uiHash1a *= iFNVPrime; } if (!is_space(szSource[2])) { //计算2FNV1 hash m_HashValue64.m_uiHash1 *= iFNVPrime; m_HashValue64.m_uiHash1 ^= szSource[2]; //计算2FNV1a hash m_HashValue64.m_uiHash1a ^= szSource[2]; m_HashValue64.m_uiHash1a *= iFNVPrime; } if (!is_space(szSource[3])) { //计算3FNV1 hash m_HashValue64.m_uiHash1 *= iFNVPrime; m_HashValue64.m_uiHash1 ^= szSource[3]; //计算3FNV1a hash m_HashValue64.m_uiHash1a ^= szSource[3]; m_HashValue64.m_uiHash1a *= iFNVPrime; } } uiLen += 4; szSource += 4; } return uiLen; }
最新发布
07-26
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值