zoukankan      html  css  js  c++  java
  • Google Guava之常见Object方法


    文中所述Guava版本基于29.0-jre,文中涉及到的代码完整示例请移步Github查看。

    常见Obejct方法使用

    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类常见方法便可以满足我们。

    equals

    由于所有类都默认继承Object,同时继承了equals方法,所以我们在比较对象是否相等的时候可以直接使用
    A.equals(B)来比较(A为null会有异常,B为null可以正常比较结果为false)。由于对null类型使用equals方式会抛出异常,导致我们在每次使用之前都会进行null判断if (null != A) {}。使用Guava的Objects.equal(Object, Object):boolean可以免于我们对对象是否为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提供同样的功能。

    hashCode

    计算对象的hash值是我们在日常编程中经常需要进行的步骤,因为大量使用了对象容器类如Map、Set等,这些对象容器类判定对象冲突时需要依赖对象的hash值。而且我们有时还要费心思的设计一个碰撞概率比较小的hash算法,保证对象hash值足够分散,同时对拥有相同值的对象计算出相同的hash值。Guava的Objects.hashCode(Object...):int提供计算对象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

    toString方法帮助我们更加详细的打印对象的内部信息,但是默认的实现对于复杂对象直接打印的是对象的内存地址,使用Guava的MoreObjects.toStringHelper可以轻松编写有用的toString方法。

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                .add("name", name)
                .add("age", age)
                .toString();
    }
    /*Output:
    Person{name=alice, age=18}
    ///:~
    

    对于使用Intellij IDEA的同学来说,则可以直接借助IDEA提供的快捷功能快速生成toString方法。

    compare/compareTo

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

    可以看到,ComparisonChainstart方法开启比较,中间是多个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有两个实例LESSGREATER,比较的过程就是三个实例之间的转变ACTIVE->LESS或者ACTIVE->GREATER

    1. ComparisonChain.start()调用后返回实例ACTIVE
    2. 调用compare方法,结果为0则返回新的实例ACTIVE,结果小于0返回实例LESS,结果大于0返回实例GREATER
    3. 若是步骤2返回的是ACTIVE则继续步骤2过程,若返回是LESSGREATER则再调用compare方法则不进行比较,直接忽略并返回LESSGREATER
    4. 最后调用result返回结果,ACTIVE返回0,LESS返回-1,GREATER返回1

    参考

  • 相关阅读:
    SLAM图优化g2o
    AI人工智能天机芯芯片
    Tengine MLOps概述
    Tengine Framework基础
    Tengine Web服务器概述
    华为MDC软件架构
    4D毫米波雷达Radar
    MindSpore循环神经网络
    构建编译TVM方法
    芯片工具链概述
  • 原文地址:https://www.cnblogs.com/weegee/p/13330147.html
Copyright © 2011-2022 走看看