需求:背景減低服務器存儲壓力,優(yōu)化客戶端上報數(shù)據(jù)大小用于節(jié)省用戶網(wǎng)絡。這個就需要字符串轉大樹或者轉枚舉。字符串md5轉為一個32位的大數(shù)烂叔,降低服務器存儲空間,優(yōu)化客戶端發(fā)送數(shù)據(jù)量
在java里面實現(xiàn)比較簡單固歪,底層提供了hashcode接口
@Override public int hashCode() {
int hash = hashCode;
if (hash == 0) {
if (count == 0) {
return 0;
}
final int end = count + offset;
final char[] chars = value;
for (int i = offset; i < end; ++i) {
hash = 31*hash + chars[i];
}
hashCode = hash;
}
return hash;
}
在iOS里模仿java實現(xiàn)一個
- (int64_t)convertStringToBigNumberInt64:(NSString *)string
{
if (string == nil || string.length == 0 )
{
return 0;
}
int i = 0;
int64_t hash = 0;
const char * charString =[string UTF8String];
for (i = 0; i < strlen(charString); i++)
{
hash = hash * 31 + charString[i];
}
return hash % INT64_MAX;
}
當然iOS中NSString 有一個接口為hash返回可返回類似的大數(shù)蒜鸡,
*/
#define HashEverythingLimit 96
#define HashNextFourUniChars(accessStart, accessEnd, pointer)
{result = result * 67503105 + (accessStart 0 accessEnd) * 16974593 + (accessStart 1 accessEnd) * 66049 + (accessStart 2 accessEnd) * 257 + (accessStart 3 accessEnd); pointer += 4;}
#define HashNextUniChar(accessStart, accessEnd, pointer)
{result = result * 257 + (accessStart 0 accessEnd); pointer++;}
CF_INTERNAL CFHashCode __CFStrHashCharacters(const UniChar* uContents, CFIndex len, CFIndex actualLen) {
CFHashCode result = actualLen;
if (len <= HashEverythingLimit) {
const UniChar* end4 = uContents + (len & ~3);
const UniChar* end = uContents + len;
while (uContents < end4) {
HashNextFourUniChars(uContents[, ], uContents); // First count in fours
}
while (uContents < end) {
HashNextUniChar(uContents[, ], uContents); // Then for the last <4 chars, count in ones...
}
} else {
const UniChar* contents, * end;
contents = uContents;
end = contents + 32;
while (contents < end) {
HashNextFourUniChars(contents[, ], contents);
}
contents = uContents + (len >> 1) - 16;
end = contents + 32;
while (contents < end) {
HashNextFourUniChars(contents[, ], contents);
}
end = uContents + len;
contents = end - 32;
while (contents < end) {
HashNextFourUniChars(contents[, ], contents);
}
}
return result + (result << (actualLen & 31));
}
由源碼可知道,字符串的長度如果大于96昼牛,其策略為取前32位 取中段32位 后取后端32位,在取值為準字符相同的情況下术瓮,其他任意位置的字符發(fā)生改變,Hash值都不會變贰健。字符串的長度如果小于等于96胞四,所有字符將參與運算,也就是說96個字符改變其中任意一個都將導致hash值的變化伶椿。
當然不是所有的32位都能滿足辜伟,有時候需要用64位來降低碰撞概率,有時候32位過多脊另,只需要16位2個字節(jié)的导狡,可以根據(jù)上面算法自己調(diào)整或者求模運算保bigNumber落在特定的整形數(shù)范圍內(nèi)。