赞
踩
Guava Hash(散列)指的是通过某种算法把数据源通过一系列的转换生成一串字符串。常见的例如hash code生成,加密字符的生成,检验字符的生成等等。接下来我们就对Guava Hash(散列)的使用做一个介绍。使用很简单。Guava Hash(散列)里面也给我们提供了很多hash算法。已经能满足我们大部分需求了。
Hash里面比较重要的类有:Hashing、HashFunction、Hasher、HashCode、Funnel、PrimitiveSink。
Hashing类是一个帮助类,里面提供的方法都是根据不同的hash算法生成对应的HashFunction对象。每个hash算法都实现了HashFunction。Hashing类里面提供的方法如下。
HashFunction有两个作用:创建Hasher对象、也可以直接根据输入条件返回HashCode结果。HashFunction里面常用函数如下:
public interface HashFunction { /** * 获取一个Hasher */ Hasher newHasher(); Hasher newHasher(int expectedInputSize); /** * 根据input生成HashCode */ HashCode hashInt(int input); HashCode hashLong(long input); HashCode hashBytes(byte[] input); HashCode hashBytes(byte[] input, int off, int len); HashCode hashBytes(ByteBuffer input); HashCode hashUnencodedChars(CharSequence input); HashCode hashString(CharSequence input, Charset charset); /** * 根据一个对象生成HashCode */ <T> HashCode hashObject(T instance, Funnel<? super T> funnel); /** * 返回此哈希生成的每个哈希代码的位数(32的倍数) */ int bits(); }
Hasher的主要作用是根据加入的数据源得到HashCode。数据源通过提供的putXxx()方法添加、hash()方法返回计算结果HashCode。
public interface Hasher extends PrimitiveSink { /** * 添加产生HashCode的数据源 */ @Override Hasher putByte(byte b); @Override Hasher putBytes(byte[] bytes); @Override Hasher putBytes(byte[] bytes, int off, int len); @Override Hasher putBytes(ByteBuffer bytes); @Override Hasher putShort(short s); @Override Hasher putInt(int i); @Override Hasher putLong(long l); @Override Hasher putFloat(float f); @Override Hasher putDouble(double d); @Override Hasher putBoolean(boolean b); @Override Hasher putChar(char c); @Override Hasher putUnencodedChars(CharSequence charSequence); @Override Hasher putString(CharSequence charSequence, Charset charset); /** * 添加一个对象数据源 */ <T> Hasher putObject(T instance, Funnel<? super T> funnel); /** * 获取到HashCode */ HashCode hash(); }
HashCode是对结果的一个封装。
public abstract class HashCode { /** * 返回此HashCode中的位数; 8的正数倍,注意哦是bit */ public abstract int bits(); /** * 把HashCode的前面四个字节转换为int(小端顺序排列) * * @throws IllegalStateException if {@code bits() < 32} */ public abstract int asInt(); /** * 把HashCode的前面八个字节转换为long(小端顺序排列) * * @throws IllegalStateException if {@code bits() < 64} */ public abstract long asLong(); /** * 如果HashCode位数足够多按照asLong()函数处理,不够直接转换为long */ public abstract long padToLong(); /** * HashCode以byte[]形式返回,字节数组的形式输出 */ // TODO(user): consider ByteString here, when that is available public abstract byte[] asBytes(); /** * HashCode放到dest里面去,并且返回放入的返回长度 */ @CanIgnoreReturnValue public int writeBytesTo(byte[] dest, int offset, int maxLength); /** * 把int转换为32位长度的HashCode */ public static HashCode fromInt(int hash); /** * 把long转换为64位长度的HashCode */ public static HashCode fromLong(long hash); /** * 把byte数组转换为HashCode */ public static HashCode fromBytes(byte[] bytes); /** * String转换为HashCode */ public static HashCode fromString(String string); /** * 返回hash code对应的字符串 */ @Override public final String toString(); }
定义了怎样将一个Object对象里面的各个属性放到PrimitiveSink里面,Hasher的putObject方法需要传入这样的对象。
Funnel
public interface Funnel<T> extends Serializable {
/**
* Sends a stream of data from the {@code from} object into the sink {@code into}. There is no
* requirement that this data be complete enough to fully reconstitute the object later.
*
* @since 12.0 (in Guava 11.0, {@code PrimitiveSink} was named {@code Sink})
*/
void funnel(T from, PrimitiveSink into);
}
PrimitiveSink
public interface PrimitiveSink { /** * 把参数放到PrimitiveSink里面去 */ PrimitiveSink putByte(byte b); PrimitiveSink putBytes(byte[] bytes); PrimitiveSink putBytes(byte[] bytes, int off, int len); PrimitiveSink putBytes(ByteBuffer bytes); 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); }
使用实例
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);
}
}
// 各种算法对应的hash code
String input = "hello, world";
// MD5
System.out.println(Hashing.md5().hashBytes(input.getBytes()).toString());
// sha256
System.out.println(Hashing.sha256().hashBytes(input.getBytes()).toString());
// sha512
System.out.println(Hashing.sha512().hashBytes(input.getBytes()).toString());
// crc32
System.out.println(Hashing.crc32().hashBytes(input.getBytes()).toString());
// MD5
System.out.println(Hashing.md5().hashUnencodedChars(input).toString());
HashFunction hf = Hashing.md5();
HashCode hc = hf.newHasher()
.putLong(10)
.putString("abc", Charsets.UTF_8)
.hash();
System.out.println(hc.toString());
@Test public void objectToHashCode() { // 需要hash的对象 Person person = new Person(27, "wu", "xing", 1990); 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(person.birthYear); } }; // md5算法 HashFunction hf = Hashing.md5(); HashCode hc = hf.newHasher() .putString("abc", Charsets.UTF_8) .putObject(person, personFunnel) .hash(); System.out.println(hc.toString()); } class Person { int id; String firstName; String lastName; int birthYear; public Person(int id, String firstName, String lastName, int birthYear) { this.id = id; this.firstName = firstName; this.lastName = lastName; this.birthYear = birthYear; } }
Guava Hash(散列)的使用很简单吧,首先在Hashing找到我们对应需要的hash算法(一般里面的这些hash算法能满足我们绝大部分的情况)。然后把数据源put进去,如果有多个数据源依次put进去就可以了。最后hash()就得到了我们最终hash的结果了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。