咱們HashMap會有一個rehash的過程,爲何呢?由於java內建的散列碼被限制爲32位,並且沒有分離散列算法和所做用的數據,因此替代算法比較難作。咱們使用HashMap的時候它自身有一個rehash的過程,因此咱們無需操心。可是若是咱們本身離開hashmap的內容,去使用Object.hashCode()就不有可能會比較坑爹了,碰撞處理咱們本身去作並不容易。可是,咱們可使用Guava的hash功能。java
Guava的Hash package底下的內容比較多:算法
它提供了不一樣的Hash算的實現,而後咱們須要先從繼承體系上面去看一下。ide
Hash算法的繼承體系:函數
Function函數的繼承體系:this
而後還有Funnel接口等,基本上已經包括Hash的組成內容,下面咱們挨個來看下都是作什麼的。google
/** * An object which can receive a stream of primitive values. @Beta public interface PrimitiveSink {···}------------------一個能接收原始數據類型流的對象?
裏面定義了一堆方法,都是putxxxxvalue:spa
PrimitiveSink putBytes(byte[] bytes, int off, int len); PrimitiveSink putShort(short s); PrimitiveSink putInt(int i); PrimitiveSink putLong(long l); PrimitiveSink putFloat(float f); PrimitiveSink putDouble(double d); PrimitiveSink putBoolean(boolean b); PrimitiveSink putChar(char c); PrimitiveSink putUnencodedChars(CharSequence charSequence); PrimitiveSink putString(CharSequence charSequence, Charset charset);
很是好理解,不贅述。而後咱們看Hasher這個核心類(接口)是幹啥的:code
@Beta public interface Hasher extends PrimitiveSink { @Override Hasher putByte(byte b); @Override Hasher putBytes(byte[] bytes); }
好吧,其實它就是把PrimitiveSink的方法給所有override了一遍,而後它新增了幾個方法:對象
<T> Hasher putObject(T instance, Funnel<? super T> funnel);------------一個簡化的put object進行hash的方法 @CheckReturnValue HashCode hash();---實際作hash的方法 @Override @Deprecated int hashCode();----不推薦使用,可是必須覆蓋的hashcode
上個代碼示例:blog
package com.congsg.learning; import com.google.common.base.Charsets; import com.google.common.hash.*; import java.nio.charset.Charset; /** * Created by congshaogang on 16/3/29. */ public class GuavaHashTest { public static void main(String[] args) { HashFunction function_0 = Hashing.md5(); HashFunction function_1 = Hashing.murmur3_128(); Hasher hasher_0 = function_0.newHasher(); Hasher hasher_1 = function_1.newHasher(); Person person = new Person(); person.setAge(27); person.setName("hahahah"); person.setAddress("北京三里屯"); person.setPhoneNumber(16666666666L); person.setMale(Male.man); HashCode code_0 = hasher_0.putInt(person.getAge()) .putString(person.getName(), Charsets.UTF_8) .putString(person.getAddress(), Charsets.UTF_8) .putLong(person.getPhoneNumber()) .putObject(person.getMale(), new Funnel<Male>() { @Override public void funnel(Male from, PrimitiveSink into) { into.putString(from.name(),Charsets.UTF_8); } }).hash(); HashCode code_1 = hasher_1.putInt(person.getAge()) .putString(person.getName(), Charsets.UTF_8) .putString(person.getAddress(), Charsets.UTF_8) .putLong(person.getPhoneNumber()) .putObject(person.getMale(), new Funnel<Male>() { @Override public void funnel(Male from, PrimitiveSink into) { into.putString(from.name(),Charsets.UTF_8); } }).hash(); System.out.println(code_0.asLong()); System.out.println(code_1.asLong()); } public enum Male { man, woman; } public static class Person { int age; String name; String address; long phoneNumber; Male male; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public long getPhoneNumber() { return phoneNumber; } public void setPhoneNumber(long phoneNumber) { this.phoneNumber = phoneNumber; } public Male getMale() { return male; } public void setMale(Male male) { this.male = male; } } }
咱們能夠利用本身去構造一些primitive的數據類型去進行hash操做,最後得到hash值。