标签:日常 return boolean 示例 learn acl 内存地址 guava 状态
文中所述Guava版本基于29.0-jre,文中涉及到的代码完整示例请移步Github查看。
Java中所有的类都有一个隐藏的公共父类,就是Object类。既然所有的类都继承自Object类,那所有的类中都包含有Object类的方法,常见的有。
equals(Object):boolean
hashCode():int
toString():String
notify():void
notifyAll():void
wait():void
wait()long:void
wait(long, int):void
Object都提供了上述方法的默认实现,但是某些情况下默认的实现不能满足我们的需求,此时就需要一些强大健全的三方实现来满足我们,Guava中提供的一些Object类常见方法便可以满足我们。
由于所有类都默认继承Object,同时继承了equals方法,所以我们在比较对象是否相等的时候可以直接使用
A.equals(B)来比较(A为null会有异常,B为null可以正常比较结果为false)。由于对null类型使用equals方式会抛出异常,导致我们在每次使用之前都会进行null判断if (null != A) {}。使用Guava的Objects.equal(Object, Object):boolan可以免于我们对对象是否为null的判定,直接使用即可。
Objects.equal(A, A);
Objects.equal(null, A);
Objects.equal(A, null);
Objects.equal(null, null);
/*Output:
true
false
false
true
///:~
注:JDK7引入的Obejcts类中的Obejcts.equals(Object, Object):boolan提供同样的功能。
计算对象的hash值是我们在日常编程中经常需要进行的步骤,因为大量使用了对象容器类如Map、Set等,这些对象容器类判定对象冲突时需要依赖对象的hash值。而且我们有时还要费心思的设计一个碰撞概率比较小的hash算法,保证对象hash值足够分散,同时对拥有相同值的对象计算出相同的hash值。Guava的[Objects.hashCode(Object...):int][4]提供计算对象hash值的一般方法,保证在大多数情况下满足我们的需求。
public class Person {
private String name;
private Integer age;
// 省略getter setter和构造函数
@Override
public int hashCode() {
return Objects.hashCode(this.name, this.age);
}
public static void main(String[] args) {
Person alice = new Person("alice", 18);
System.out.println(alice.hashCode());
}
}
/*Output:
-1414972077
///:~
hash方法的实现如下
public static int hashCode(Object a[]) {
if (a == null)
return 0;
int result = 1;
for (Object element : a)
result = 31 * result + (element == null ? 0 : element.hashCode());
return result;
}
对象是null时hash值为0,值为null则该值的hash值为0,其余的值直接调用JDK的native方法进行hash值的计算(若是想深入了解可以查询hashCode()方法在native的实现)。
注:JDK7引入的Obejcts类中的Obejcts.hash(Object...):int提供同样的功能。
toString方法帮助我们更加详细的打印对象的内部信息,但是默认的实现对于复杂对象直接打印的是对象的内存地址,使用Guava的Objects.toStringHelper可以轻松编写有用的toString方法。
Objects.toStringHelper(this).add("x", 1).toString();
Objects.toStringHelper("MyObject").add("x", 1).toString();
/*Output:
ClassName{x=1}
MyObject{x=1}
///:~
注:目前版本Guava尚未提供此方法的实现
对于使用Intellij IDEA的同学来说,则可以直接借助IDEA提供的快捷功能快速生成toString方法。
Java中对象的比较一般有两种办法,一是继承Comparable接口并实现compareTo(T o)方法,另外一种是创建Comparator类。Guava提供了一种在compareTo(T o)方法中快速比较对象的功能ComparisonChain。
public class Person implements Comparable<Person> {
private String name;
private Integer age;
// 省略getter setter和构造函数
@Override
public int compareTo(Person other) {
return ComparisonChain.start()
.compare(this.name, other.name)
.compare(this.age, other.age, Ordering.natural().nullsLast())
.result();
}
}
可以看到,ComparisonChain以start方法开启比较,中间是多个compare方法,最后调用result返回结果,而且在使用compare的时候,可以使用Guava提供的Ordering来实现更多的功能(关于Guava Ordering的介绍请移步Google Guava之Ordering)。
ComparisonChain执行一种懒比较:它执行比较操作直至发现非零的结果,在那之后的比较输入将被忽略。这句话可能不是那么好理解,我们结合上面的示例来分析这句话。
return ComparisonChain.start() \\ 1
.compare(this.name, other.name) \\ 2
.compare(this.age, other.age, Ordering.natural().nullsLast()) \\ 3
.result(); \\ 4
1处代码开启比较,如果在2处代码比较后结果非零(即this.name小于other.name或this.name大于other.name),3处的代码即忽略执行,直接在4处得到结果。
Guava是如何实现这种懒比较呢?Guava实现此项功能使用了100多行的代码,下面我们来分析这100多行的代码。
public abstract class ComparisonChain {
// 调用start方法返回ACTIVE
private static final ComparisonChain ACTIVE = new ComparisonChain() {
public ComparisonChain compare(Comparable left, Comparable right) {
return this.classify(left.compareTo(right));
}
public <T> ComparisonChain compare(@Nullable T left, @Nullable T right, Comparator<T> comparator) {
return this.classify(comparator.compare(left, right));
}
public ComparisonChain compare(int left, int right) {
return this.classify(Ints.compare(left, right));
}
public ComparisonChain compare(long left, long right) {
return this.classify(Longs.compare(left, right));
}
public ComparisonChain compare(float left, float right) {
return this.classify(Float.compare(left, right));
}
public ComparisonChain compare(double left, double right) {
return this.classify(Double.compare(left, right));
}
public ComparisonChain compareTrueFirst(boolean left, boolean right) {
return this.classify(Booleans.compare(right, left));
}
public ComparisonChain compareFalseFirst(boolean left, boolean right) {
return this.classify(Booleans.compare(left, right));
}
// 所有的compare方法最终都要调用classify方法,classify方法接收的是比较后的值,比较结果为0则返回ComparisonChain.ACTIVE,否则依据结果返回ComparisonChain.LESS或ComparisonChain.GREATER,ComparisonChain.LESS和ComparisonChain.GREATER都是ComparisonChain的子类InactiveComparisonChain实例
ComparisonChain classify(int result) {
return result < 0 ? ComparisonChain.LESS : (result > 0 ? ComparisonChain.GREATER : ComparisonChain.ACTIVE);
}
public int result() {
return 0;
}
};
// LESS使用-1作为构造函数的参数,表示对LESS调用result返回-1
private static final ComparisonChain LESS = new ComparisonChain.InactiveComparisonChain(-1);
// GREATER使用1作为构造函数的参数,表示对GREATER调用result返回1
private static final ComparisonChain GREATER = new ComparisonChain.InactiveComparisonChain(1);
private ComparisonChain() {
}
public static ComparisonChain start() {
return ACTIVE;
}
public abstract ComparisonChain compare(Comparable<?> var1, Comparable<?> var2);
public abstract <T> ComparisonChain compare(@Nullable T var1, @Nullable T var2, Comparator<T> var3);
public abstract ComparisonChain compare(int var1, int var2);
public abstract ComparisonChain compare(long var1, long var3);
public abstract ComparisonChain compare(float var1, float var2);
public abstract ComparisonChain compare(double var1, double var3);
/** @deprecated */
@Deprecated
public final ComparisonChain compare(Boolean left, Boolean right) {
return this.compareFalseFirst(left, right);
}
public abstract ComparisonChain compareTrueFirst(boolean var1, boolean var2);
public abstract ComparisonChain compareFalseFirst(boolean var1, boolean var2);
public abstract int result();
private static final class InactiveComparisonChain extends ComparisonChain {
final int result;
InactiveComparisonChain(int result) {
super(null);
this.result = result;
}
// 一旦内部状态由ACTIVE转为InactiveComparisonChain,后续再调用compare都不再执行真正的比较操作,直接忽略
public ComparisonChain compare(@Nullable Comparable left, @Nullable Comparable right) {
return this;
}
public <T> ComparisonChain compare(@Nullable T left, @Nullable T right, @Nullable Comparator<T> comparator) {
return this;
}
public ComparisonChain compare(int left, int right) {
return this;
}
public ComparisonChain compare(long left, long right) {
return this;
}
public ComparisonChain compare(float left, float right) {
return this;
}
public ComparisonChain compare(double left, double right) {
return this;
}
public ComparisonChain compareTrueFirst(boolean left, boolean right) {
return this;
}
public ComparisonChain compareFalseFirst(boolean left, boolean right) {
return this;
}
public int result() {
return this.result;
}
}
}
ComparisonChain内部有一个实例ACTIVE,和一个子类InactiveComparisonChain,子类InactiveComparisonChain有两个实例LESS和GREATER,比较的过程就是三个实例之间的转变ACTIVE->LESS或者ACTIVE->GREATER。
ComparisonChain.start()调用后返回实例ACTIVE;compare方法,结果为0则返回新的实例ACTIVE,结果小于0返回实例LESS,结果大于0返回实例GREATER;ACTIVE则继续步骤2过程,若返回是LESS或GREATER则再调用compare方法则不进行比较,直接忽略并返回LESS或GREATER;result返回结果,ACTIVE返回0,LESS返回-1,GREATER返回1。标签:日常 return boolean 示例 learn acl 内存地址 guava 状态
原文地址:https://www.cnblogs.com/weegee/p/13330147.html