Class ComparisonChain


  • @GwtCompatible
    public abstract class ComparisonChain
    extends java.lang.Object
    A utility for performing a chained comparison statement. Note: Java 8+ users should generally prefer the methods in Comparator; see below.

    Example usage of ComparisonChain:

    
     public int compareTo(Foo that) {
       return ComparisonChain.start()
           .compare(this.aString, that.aString)
           .compare(this.anInt, that.anInt)
           .compare(this.anEnum, that.anEnum, Ordering.natural().nullsLast())
           .result();
     }
     

    The value of this expression will have the same sign as the first nonzero comparison result in the chain, or will be zero if every comparison result was zero.

    Note: ComparisonChain instances are immutable. For this utility to work correctly, calls must be chained as illustrated above.

    Performance note: Even though the ComparisonChain caller always invokes its compare methods unconditionally, the ComparisonChain implementation stops calling its inputs' compareTo and compare methods as soon as one of them returns a nonzero result. This optimization is typically important only in the presence of expensive compareTo and compare implementations.

    See the Guava User Guide article on ComparisonChain.

    Java 8+ equivalents

    If you are using Java version 8 or greater, you should generally use the static methods in Comparator instead of ComparisonChain. The example above can be implemented like this:
    
     import static java.util.Comparator.comparing;
     import static java.util.Comparator.nullsLast;
     import static java.util.Comparator.naturalOrder;
    
     ...
       private static final Comparator<Foo> COMPARATOR =
           comparing((Foo foo) -> foo.aString)
               .thenComparing(foo -> foo.anInt)
               .thenComparing(foo -> foo.anEnum, nullsLast(naturalOrder()));
    
       @Override
       public int compareTo(Foo that) {
         return COMPARATOR.compare(this, that);
       }
     

    With method references it is more succinct: comparing(Foo::aString) for example.

    Using Comparator avoids certain types of bugs, for example when you meant to write .compare(a.foo, b.foo) but you actually wrote .compare(a.foo, a.foo) or .compare(a.foo, b.bar). ComparisonChain also has a potential performance problem that Comparator doesn't: it evaluates all the parameters of all the .compare calls, even when the result of the comparison is already known from previous .compare calls. That can be expensive.

    Since:
    2.0
    Author:
    Mark Davis, Kevin Bourrillion
    • Method Summary

      All Methods Static Methods Instance Methods Abstract Methods Concrete Methods Deprecated Methods 
      Modifier and Type Method Description
      abstract ComparisonChain compare​(double left, double right)
      Compares two double values as specified by Double.compare(double, double), if the result of this comparison chain has not already been determined.
      abstract ComparisonChain compare​(float left, float right)
      Compares two float values as specified by Float.compare(float, float), if the result of this comparison chain has not already been determined.
      abstract ComparisonChain compare​(int left, int right)
      Compares two int values as specified by Ints.compare(int, int), if the result of this comparison chain has not already been determined.
      abstract ComparisonChain compare​(long left, long right)
      Compares two long values as specified by Longs.compare(long, long), if the result of this comparison chain has not already been determined.
      ComparisonChain compare​(java.lang.Boolean left, java.lang.Boolean right)
      Deprecated.
      Use compareFalseFirst(boolean, boolean); or, if the parameters passed are being either negated or reversed, undo the negation or reversal and use compareTrueFirst(boolean, boolean).
      abstract ComparisonChain compare​(java.lang.Comparable<?> left, java.lang.Comparable<?> right)
      Compares two comparable objects as specified by Comparable.compareTo(T), if the result of this comparison chain has not already been determined.
      abstract <T extends @Nullable java.lang.Object>
      ComparisonChain
      compare​(T left, T right, java.util.Comparator<T> comparator)
      Compares two objects using a comparator, if the result of this comparison chain has not already been determined.
      abstract ComparisonChain compareFalseFirst​(boolean left, boolean right)
      Compares two boolean values, considering false to be less than true, if the result of this comparison chain has not already been determined.
      abstract ComparisonChain compareTrueFirst​(boolean left, boolean right)
      Compares two boolean values, considering true to be less than false, if the result of this comparison chain has not already been determined.
      abstract int result()
      Ends this comparison chain and returns its result: a value having the same sign as the first nonzero comparison result in the chain, or zero if every result was zero.
      static ComparisonChain start()
      Begins a new chained comparison statement.
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Method Detail

      • start

        public static ComparisonChain start()
        Begins a new chained comparison statement. See example in the class documentation.
      • compare

        public abstract ComparisonChain compare​(java.lang.Comparable<?> left,
                                                java.lang.Comparable<?> right)
        Compares two comparable objects as specified by Comparable.compareTo(T), if the result of this comparison chain has not already been determined.

        This method is declared to accept any 2 Comparable objects, even if they are not mutually comparable. If you pass objects that are not mutually comparable, this method may throw an exception. (The reason for this decision is lost to time, but the reason might be that we wanted to support legacy classes that implement the raw type Comparable (instead of implementing Comparable<Foo>) without producing warnings. If so, we would prefer today to produce warnings in that case, and we may change this method to do so in the future. Support for raw Comparable types in Guava in general is tracked as #989.)

        Throws:
        java.lang.ClassCastException - if the parameters are not mutually comparable
      • compare

        public abstract <T extends @Nullable java.lang.Object> ComparisonChain compare​(T left,
                                                                                       T right,
                                                                                       java.util.Comparator<T> comparator)
        Compares two objects using a comparator, if the result of this comparison chain has not already been determined.
      • compare

        public abstract ComparisonChain compare​(float left,
                                                float right)
        Compares two float values as specified by Float.compare(float, float), if the result of this comparison chain has not already been determined.
      • compare

        public abstract ComparisonChain compare​(double left,
                                                double right)
        Compares two double values as specified by Double.compare(double, double), if the result of this comparison chain has not already been determined.
      • compareTrueFirst

        public abstract ComparisonChain compareTrueFirst​(boolean left,
                                                         boolean right)
        Compares two boolean values, considering true to be less than false, if the result of this comparison chain has not already been determined.

        Java 8+ users: you can get the equivalent from Booleans.trueFirst(). For example:

         Comparator.comparing(Foo::isBar, Booleans.trueFirst())
         
        Since:
        12.0
      • compareFalseFirst

        public abstract ComparisonChain compareFalseFirst​(boolean left,
                                                          boolean right)
        Compares two boolean values, considering false to be less than true, if the result of this comparison chain has not already been determined.

        Java 8+ users: you can get the equivalent from Booleans.falseFirst(). For example:

         Comparator.comparing(Foo::isBar, Booleans.falseFirst())
         
        Since:
        12.0 (present as compare since 2.0)
      • result

        public abstract int result()
        Ends this comparison chain and returns its result: a value having the same sign as the first nonzero comparison result in the chain, or zero if every result was zero.