iOS 数据统计优化策略 字符串转大数 OC类似java的has
2017-05-22 本文已影响135人
熊猫人和熊猫君
需求:背景减低服务器存储压力,优化客户端上报数据大小用于节省用户网络。这个就需要字符串转大树或者转枚举。字符串md5转为一个32位的大数,降低服务器存储空间,优化客户端发送数据量
在java里面实现比较简单,底层提供了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实现一个
- (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返回可返回类似的大数,
*/
#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位,在取值为准字符相同的情况下,其他任意位置的字符发生改变,Hash值都不会变。字符串的长度如果小于等于96,所有字符将参与运算,也就是说96个字符改变其中任意一个都将导致hash值的变化。
当然不是所有的32位都能满足,有时候需要用64位来降低碰撞概率,有时候32位过多,只需要16位2个字节的,可以根据上面算法自己调整或者求模运算保bigNumber落在特定的整形数范围内。