基于Java实现常用于布隆过滤的hash函数

在网站基于C语言实现了常用hash函数,遗憾没有Java版本的,这里基于Java实现了9个hash函数,可以用于设计基于Redis的Bitmap的布隆过滤器。

代码地址:GitHub

代码:

import javax.print.attribute.HashPrintServiceAttributeSet;

/**
 * 9个常用hash计算函数Java语言实现
 * C语言实现地址:http://www.partow.net/programming/hashfunctions/index.html
 */
public class HashHelper {
    private static long maxUInt = 4294967296L;

    /**
     * Java没有无符号类型,所以无法表达C语言中的unsigned int
     * 但我们可以用long表达更大的数值
     * 然后,我们把计算出来的值给转换成源代码中溢出的值
     *
     * @param str
     * @return
     */
    public static long RSHash(String str) {
        int length = str.length();
        long b = 378551;
        long a = 63689;
        long hash = 0;
        char[] arrStr = str.toCharArray();
        for (int i = 0; i < length; ++i) {
            int ascii = Integer.valueOf(arrStr[i]);
            hash = hash * a + ascii;
            if (hash > maxUInt) {
                hash = hash % maxUInt;
            }
            a = a * b;
            if (a > maxUInt) {
                a = a % maxUInt;
            }
        }
        return hash;
    }

    public static long JSHash(String str) {
        int length = str.length();
        long hash = 1315423911L;
        char[] arrStr = str.toCharArray();
        for (int i = 0; i < length; ++i) {
            int ascii = Integer.valueOf(arrStr[i]);
            long temp1 = hash << 5;
            if (temp1 > maxUInt) {
                temp1 = temp1 % maxUInt;
            }
            long temp2 = hash >> 2;
            if (temp2 > maxUInt) {
                temp2 = temp1 % maxUInt;
            }
            hash = hash ^ (temp1 + ascii + temp2);
            if (hash > maxUInt) {
                hash = hash % maxUInt;
            }
        }
        return hash;
    }

    public static long PJWHash(String str) {
        // 源代码这个值是int的字节数*8。在语言中,int类型在32位系统中是2位,在64位系统中是4位,目前基本都是64位的系统啦。
        long bitsInUnsignedInt = 4 * 8;
        long threesQuarters = (bitsInUnsignedInt * 3) / 4;
        long oneEighth = bitsInUnsignedInt / 8;
        long highBits = (0xFFFFFFFF) << (bitsInUnsignedInt - oneEighth);
        long hash = 0;
        long test = 0;
        int length = str.length();
        char[] arrStr = str.toCharArray();
        for (int i = 0; i < length; ++i) {
            int ascii = Integer.valueOf(arrStr[i]);
            hash = (hash << oneEighth) + ascii;
            if (hash > maxUInt) {
                hash = hash % maxUInt;
            }
            if ((test = hash & highBits) != 0) {
                long temp2 = test >> threesQuarters;
                if (temp2 > maxUInt) {
                    temp2 = temp2 % maxUInt;
                }
                long temp3 = hash ^ temp2;
                if (temp3 > maxUInt) {
                    temp3 = temp3 % maxUInt;
                }
                hash = temp3 & (~highBits);
                if (hash > maxUInt) {
                    hash = hash % maxUInt;
                }
                System.out.println("hash:" + hash);
            }
        }
        return hash;
    }

    public static long ELFHash(String str) {
        long hash = 0;
        long x = 0;
        int length = str.length();
        char[] arrStr = str.toCharArray();
        for (int i = 0; i < length; ++i) {
            int ascii = Integer.valueOf(arrStr[i]);
            hash = hash << 4;
            if (hash > maxUInt) {
                hash = hash % maxUInt;
            }
            hash = hash + ascii;
            if (hash > maxUInt) {
                hash = hash % maxUInt;
            }
            x = hash & 0xF000000L;
            if (x > maxUInt) {
                x = x % maxUInt;
            }
            if (x != 0) {
                hash ^= (x >> 24);
                if (hash > maxUInt) {
                    hash = hash % maxUInt;
                }
            }
            hash &= ~x;
            if (hash > maxUInt) {
                hash = hash % maxUInt;
            }
        }
        return hash;
    }


    public static long BKDRHash(String str) {
        // 种子数可以选择: 31 131 1313 13131 131313 etc..
        long seed = 131;
        long hash = 0;
        char[] arrStr = str.toCharArray();
        int length = str.length();
        for (int i = 0; i < length; ++i) {
            hash = hash * seed;
            if (hash > maxUInt) {
                hash = hash % maxUInt;
            }
            int ascii = Integer.valueOf(arrStr[i]);
            hash = hash + ascii;
            if (hash > maxUInt) {
                hash = hash % maxUInt;
            }
        }
        return hash;
    }

    public static long SDBMHash(String str) {
        long hash = 0;
        int length = str.length();
        char[] arrStr = str.toCharArray();
        for (int i = 0; i < length; ++i) {
            long temp1 = hash << 6;
            if (temp1 > maxUInt) {
                temp1 = temp1 % maxUInt;
            }
            long temp2 = hash << 16;
            if (temp2 > maxUInt) {
                temp2 = temp2 % maxUInt;
            }
            int ascii = Integer.valueOf(arrStr[i]);
            hash = ascii + temp1 + temp2 - hash;
            if (hash > maxUInt) {
                hash = hash % maxUInt;
            }
        }
        return hash;
    }

    public static long DJBHash(String str) {
        long hash = 5381;
        int length = str.length();
        char[] arrStr = str.toCharArray();
        for (int i = 0; i < length; ++i) {
            long temp1 = hash << 5;
            if (temp1 > maxUInt) {
                temp1 = temp1 % maxUInt;
            }
            int ascii = Integer.valueOf(arrStr[i]);
            hash = (temp1 + hash) + ascii;
            if (hash > maxUInt) {
                hash = hash % maxUInt;
            }
        }
        return hash;
    }

    public static long DEKHash(String str) {
        int length = str.length();
        long hash = length;
        char[] arrStr = str.toCharArray();
        for (int i = 0; i < length; ++i) {
            long temp1 = hash << 5;
            if (temp1 > maxUInt) {
                temp1 = temp1 % maxUInt;
            }
            long temp2 = hash >> 27;
            if (temp2 > maxUInt) {
                temp2 = temp2 % maxUInt;
            }
            int ascii = Integer.valueOf(arrStr[i]);
            hash = temp1 ^ temp2 ^ ascii;
            if (hash > maxUInt) {
                hash = hash % maxUInt;
            }
        }
        return hash;
    }

    public static long APHash(String str) {
        long hash = 0xAAAAAAAAL;
        int length = str.length();
        char[] arrStr = str.toCharArray();
        for (int i = 0; i < length; ++i) {
            long temp1 = hash << 7;
            if (temp1 > maxUInt) {
                temp1 = temp1 % maxUInt;
            }
            long temp2 = hash >> 3;
            if (temp2 > maxUInt) {
                temp2 = temp2 % maxUInt;
            }
            long temp3 = hash << 11;
            if (temp3 > maxUInt) {
                temp3 = temp3 % maxUInt;
            }
            long temp4 = hash >> 5;
            if (temp4 > maxUInt) {
                temp4 = temp4 % maxUInt;
            }
            int ascii = Integer.valueOf(arrStr[i]);
            long temp5 = ~(temp3 + (ascii ^ temp4));
            if (temp5 > maxUInt) {
                temp5 = temp5 % maxUInt;
            } else if (temp5 < 0) {
                temp5 = maxUInt + temp5;
            }
            hash ^= ((i & 1) == 0) ? (temp1 ^ ascii * temp2) : temp5;
            if (hash > maxUInt) {
                hash = hash % maxUInt;
            }
        }
        return hash;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值