Guava官方文档中文版(十二)-哈希

哈希(Hashing)

概览

Java的内嵌的hash代码的概念被限制到32位,而且没有提供hash算法和他们处理的数据之间提供分离,所以替代的hash算法不能非常容易的被替换。而且hashCode的实现往往质量很差,在某种程度上因为他们最终依赖其他已存在的低质量hashCode实现,包含在许多JDK中的实现。

Object.hashCode实现往往非常快,但是存在非常弱的防碰撞功能和没有位分离的期望。这使得他们非常适合在哈希表中使用,因为额外的碰撞只会对性能造成轻微的影响,而糟糕的位分散很容易使用二级哈希函数(Java中所有的合理的哈希表实现都使用)来纠正。对于在简单哈希表之外的许多哈希函数的用途,Object.hashCode总是达不到要求 – 因此出现了com.google.common.hash

结构

查看包的Javadoc,我们看到很多不同的类型,但是他们如何组合到一起并不明显。

我们看一段使用此类库简单的代码。

HashFunction hf = Hashing.md5();
HashCode hc = hf.newHasher()
       .putLong(id)
       .putString(name, Charsets.UTF_8)
       .putObject(person, personFunnel)
       .hash();
HashFunction

HashFunction是纯粹的无状态函数,它将一个任意的数据块映射到固定数量的bit,具有相等的输入总是产出相等的输出,不相等的输入总是不相等的输出的属性。

Hasher

可以向HashFunction请求有状态的Hasher,其提供流式语法来添加数据到hash,然后检索hash值。Hasher可以接受任何原生类型输入,字节数组,字节数组片,字符串,某些字符集字符串等等,或者通过合适的Funnel提供的其他Object

Hasher实现了PrimitiveSink接口,此接口为接受原生类型值的对象指定流式API。

Funnel

Funnel描述了如何将特别的对象分解为原生类型字段值。例如,如果我们有:

class Person {
  final int id;
  final String firstName;
  final String lastName;
  final int birthYear;
}

我们的Funnel可能看起来像:

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);
  }
};

注意:putString("abc", Charsets.UTF_8).putString("def", Charsets.UTF_8)是完全等价于putString("ab", Charsets.UTF_8).putString("cdef", Charsets.UTF_8),因为他们产生相同的字节序列。这可能会导致意外的哈希冲突。添加某种分割器可以帮助消除意外的哈希冲突。

HashCode

一旦Hasher已经给出所有它的输入,它的hash()方法就可以用来检索一个HashCodeHashCode支持相等性测试等,以及asInt(),asLong(),asBytes()方法以及额外的writeBytesTo(array, offset, maxLength),其将hash的第一个maxLength字节写入到数组。

BloomFilter(布隆过滤器)

Bloom过滤器是一个哈希的令人愉快的应用程序,不能简单地使用Object.hashCode()来完成。简单来说,Bloom过滤器是概率性的数据结构,允许你测试一个对象是否明确在过滤器中,或者可能被添加到Bloom过滤器中。 Wikipedia还算全面,我们建议这个教程

我们的哈希类库有一个内建的Bloom过滤器实现,只要求你实现一个Funnel将你的类型分解为原生类型。你可以使用create(Funnel funnel, int expectedInsertions, double falsePositiveProbability)获取新颖的BloomFilter<T>,或者只接收默认的3%的false可能性。BloomFilter<T>提供boolean mightContain(T)void put(T)方法,这两个方法不言自明的。

BloomFilter<Person> friends = BloomFilter.create(personFunnel, 500, 0.01);
for (Person friend : friendsList) {
  friends.put(friend);
}
// much later
if (friends.mightContain(someone)) {
  // the probability that someone reached this place if they aren't a friend is
  // 1% we might, for example, start asynchronously loading things for someone
  // while we do a more expensive exact check
}

哈希

Hashing工具类提供多个常用的哈希函数和工具来操作HashCode对象。

提供的哈希函数

要了解全部列表,请查看Hashing文档

HashCode操作
方法描述
HashCode combineOrdered(Iterable<HashCode>)以有序的方式组合哈希码,如果从此方法获取的两个哈希是相同的,则很可能每个哈希值都是以相同的顺序从相同的哈希值计算出来的
HashCode combineUnordered(Iterable<HashCode>)以无序的方式组合哈希码,如果从此方法获取的两个哈希值是相同的,则很可能每个哈希值都是以相同的顺序从相同的哈希值计算出来的
int consistentHash(HashCode, int buckets)为哈希码分配一致的“bucket(桶)”,以最大限度的减少随着桶的数量的增长而重新映射的需要。详情请查看Wikipedia
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值