一.Guava提供了一些方法帮助我们生成hash值。
主要有下面几个帮助类:
HashFunction: hash函数,可以用于创建Hasher对象
Hashing:定义了一些hash函数,主要有md5(),murmur3_128(),murmur3_32(),sha1(),sha256(),sha512(),goodFastHash(int bits)。
Hasher:计算hash值,提供了putXxx()方法用于添加数据,以及hash()方法返回计算结果HashCode。
HashCode:hash值计算结果
Funnel:定义了怎样将一个Object对象分解为primitive 类型,Hasher的putObject方法需要传入这样的对象。
示例:
class Person {
final int id;
final String firstName;
final String lastName;
final int birthYear;
}
//Funnel定义了Person对象如何分解为primitive 类型,以便Hasher的putObject方式使用
Funnel<Person> personFunnel = new Funnel<Person>() {
@Override
public void funnel(Person person, PrimitiveSink into) {
into
.putInt(person.id)
.putString(person.firstName, Charsets.UTF_8)
.putString(person.lastName, Charsets.UTF_8)
.putInt(birthYear);
}
};
HashFunction hf = Hashing.md5();
HashCode hc = hf.newHasher()
.putLong(id)
.putString(name, Charsets.UTF_8)
.putObject(person, personFunnel) //putObject方法
.hash();
System.out.println(hc. asInt ()); //hash结果输出
System.out.println(hc. asBytes()); //hash结果输出
二. BloomFilter
BloomFilter是一种算法,用于判断一个对象是否包含在一个集合里面。这种做法只需要占用很低的空间,效率也非常高。但是判断结果会有一定的误差。
大概实现方式为:
1. 先定义一个n位的二进制数组。
2. 对任意一个对象,采用m种hash函数计算它的hash值,得到的每个hash值映射到数组的某一位,把二进制数组的这一位就标记为1。
3. 判断一个对象是否包含在集合中时,采用同样的m种hash函数计算hash值,同样映射到数组中的位,如果这些位全部为1,则表示该对象确实很可能包含于集合中,只要有一位不为1,则该对象一定不包含于集合中。
自从Burton Bloom在70年代提出Bloom Filter之后,Bloom Filter就被广泛用于拼写检查和数据库系统中。近一二十年,伴随着网络的普及和发展,Bloom Filter在网络领域获得了新生,各种Bloom Filter变种和新的应用不断出现。
这种做法适用于能够容忍一定的错误率的场景。Guava中的BloomFilter实现了这种算法。
BloomFilter<Person> friends = BloomFilter.create(personFunnel, 500, 0.01);
for(Person friend : friendsList) {
friends.put(friend);
}
// much later
if (friends.mightContain(dude)) {
// the probability that dude reached this place if he isn't a friend is 1%
// we might, for example, start asynchronously loading things for dude while we do a more expensive exact check
}
BloomFilter.create方法创建了BloomFilter对象,三个参数分别指定了Object分解为primitive 的方式(因为Hasher.putObject方法需要这个参数),集合的预期大小,以及容错率。
BloomFilter的hash函数策略目前只有一种BloomFilterStrategies. MURMUR128_MITZ_32,它可以根据你期望的集合大小和容错率来计划hash函数的个数及二进制数组的大小。
BloomFilter.put方法可以将对象放到集合中
BloomFilter. mightContain用于判断对象是否可能包含于集合中
BloomFilter. expectedFpp用于得到目前的错误率(这个不一定跟create方法传入的容错率参数相等,因为目前加入集合中的元素个数不一定等于crate方法传入的预期元素个数)