美文网首页iOSiOS学习笔记iOS Developer
iOS 数据统计优化策略 字符串转大数 OC类似java的has

iOS 数据统计优化策略 字符串转大数 OC类似java的has

作者: 熊猫人和熊猫君 | 来源:发表于2017-05-22 19:51 被阅读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落在特定的整形数范围内。

    源码来自,https://github.com/DmitrySkiba/itoa-cleancf/blob/9e20484344430008a8b1a0e7c0f29aa06eac3d1e/src/CoreFoundation/CFString/CFString_Hash.c

    相关文章

      网友评论

        本文标题:iOS 数据统计优化策略 字符串转大数 OC类似java的has

        本文链接:https://www.haomeiwen.com/subject/kheixxtx.html