001/* 002 * Copyright (C) 2009 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.google.common.collect; 018 019import com.google.common.annotations.GwtCompatible; 020import com.google.common.primitives.Booleans; 021import com.google.common.primitives.Ints; 022import com.google.common.primitives.Longs; 023 024import java.util.Comparator; 025 026import javax.annotation.Nullable; 027 028/** 029 * A utility for performing a "lazy" chained comparison statement, which 030 * performs comparisons only until it finds a nonzero result. For example: 031 * <pre> {@code 032 * 033 * public int compareTo(Foo that) { 034 * return ComparisonChain.start() 035 * .compare(this.aString, that.aString) 036 * .compare(this.anInt, that.anInt) 037 * .compare(this.anEnum, that.anEnum, Ordering.natural().nullsLast()) 038 * .result(); 039 * }}</pre> 040 * 041 * The value of this expression will have the same sign as the <i>first 042 * nonzero</i> comparison result in the chain, or will be zero if every 043 * comparison result was zero. 044 * 045 * <p>Once any comparison returns a nonzero value, remaining comparisons are 046 * "short-circuited". 047 * 048 * <p>See the Guava User Guide article on <a href= 049 * "http://code.google.com/p/guava-libraries/wiki/CommonObjectUtilitiesExplained#compare/compareTo"> 050 * {@code ComparisonChain}</a>. 051 * 052 * @author Mark Davis 053 * @author Kevin Bourrillion 054 * @since 2.0 055 */ 056@GwtCompatible 057public abstract class ComparisonChain { 058 private ComparisonChain() {} 059 060 /** 061 * Begins a new chained comparison statement. See example in the class 062 * documentation. 063 */ 064 public static ComparisonChain start() { 065 return ACTIVE; 066 } 067 068 private static final ComparisonChain ACTIVE = new ComparisonChain() { 069 @SuppressWarnings("unchecked") 070 @Override public ComparisonChain compare( 071 Comparable left, Comparable right) { 072 return classify(left.compareTo(right)); 073 } 074 @Override public <T> ComparisonChain compare( 075 @Nullable T left, @Nullable T right, Comparator<T> comparator) { 076 return classify(comparator.compare(left, right)); 077 } 078 @Override public ComparisonChain compare(int left, int right) { 079 return classify(Ints.compare(left, right)); 080 } 081 @Override public ComparisonChain compare(long left, long right) { 082 return classify(Longs.compare(left, right)); 083 } 084 @Override public ComparisonChain compare(float left, float right) { 085 return classify(Float.compare(left, right)); 086 } 087 @Override public ComparisonChain compare(double left, double right) { 088 return classify(Double.compare(left, right)); 089 } 090 @Override public ComparisonChain compareTrueFirst(boolean left, boolean right) { 091 return classify(Booleans.compare(right, left)); // reversed 092 } 093 @Override public ComparisonChain compareFalseFirst(boolean left, boolean right) { 094 return classify(Booleans.compare(left, right)); 095 } 096 ComparisonChain classify(int result) { 097 return (result < 0) ? LESS : (result > 0) ? GREATER : ACTIVE; 098 } 099 @Override public int result() { 100 return 0; 101 } 102 }; 103 104 private static final ComparisonChain LESS = new InactiveComparisonChain(-1); 105 106 private static final ComparisonChain GREATER = new InactiveComparisonChain(1); 107 108 private static final class InactiveComparisonChain extends ComparisonChain { 109 final int result; 110 111 InactiveComparisonChain(int result) { 112 this.result = result; 113 } 114 @Override public ComparisonChain compare( 115 @Nullable Comparable left, @Nullable Comparable right) { 116 return this; 117 } 118 @Override public <T> ComparisonChain compare(@Nullable T left, 119 @Nullable T right, @Nullable Comparator<T> comparator) { 120 return this; 121 } 122 @Override public ComparisonChain compare(int left, int right) { 123 return this; 124 } 125 @Override public ComparisonChain compare(long left, long right) { 126 return this; 127 } 128 @Override public ComparisonChain compare(float left, float right) { 129 return this; 130 } 131 @Override public ComparisonChain compare(double left, double right) { 132 return this; 133 } 134 @Override public ComparisonChain compareTrueFirst(boolean left, boolean right) { 135 return this; 136 } 137 @Override public ComparisonChain compareFalseFirst(boolean left, boolean right) { 138 return this; 139 } 140 @Override public int result() { 141 return result; 142 } 143 } 144 145 /** 146 * Compares two comparable objects as specified by {@link 147 * Comparable#compareTo}, <i>if</i> the result of this comparison chain 148 * has not already been determined. 149 */ 150 public abstract ComparisonChain compare( 151 Comparable<?> left, Comparable<?> right); 152 153 /** 154 * Compares two objects using a comparator, <i>if</i> the result of this 155 * comparison chain has not already been determined. 156 */ 157 public abstract <T> ComparisonChain compare( 158 @Nullable T left, @Nullable T right, Comparator<T> comparator); 159 160 /** 161 * Compares two {@code int} values as specified by {@link Ints#compare}, 162 * <i>if</i> the result of this comparison chain has not already been 163 * determined. 164 */ 165 public abstract ComparisonChain compare(int left, int right); 166 167 /** 168 * Compares two {@code long} values as specified by {@link Longs#compare}, 169 * <i>if</i> the result of this comparison chain has not already been 170 * determined. 171 */ 172 public abstract ComparisonChain compare(long left, long right); 173 174 /** 175 * Compares two {@code float} values as specified by {@link 176 * Float#compare}, <i>if</i> the result of this comparison chain has not 177 * already been determined. 178 */ 179 public abstract ComparisonChain compare(float left, float right); 180 181 /** 182 * Compares two {@code double} values as specified by {@link 183 * Double#compare}, <i>if</i> the result of this comparison chain has not 184 * already been determined. 185 */ 186 public abstract ComparisonChain compare(double left, double right); 187 188 /** 189 * Compares two {@code boolean} values, considering {@code true} to be less 190 * than {@code false}, <i>if</i> the result of this comparison chain has not 191 * already been determined. 192 * 193 * @since 12.0 194 */ 195 public abstract ComparisonChain compareTrueFirst(boolean left, boolean right); 196 197 /** 198 * Compares two {@code boolean} values, considering {@code false} to be less 199 * than {@code true}, <i>if</i> the result of this comparison chain has not 200 * already been determined. 201 * 202 * @since 12.0 (present as {@code compare} since 2.0) 203 */ 204 public abstract ComparisonChain compareFalseFirst(boolean left, boolean right); 205 206 /** 207 * Old name of {@link #compareFalseFirst}. 208 * 209 * @deprecated Use {@link #compareFalseFirst}; or, if the parameters passed 210 * are being either negated or reversed, undo the negation or reversal and 211 * use {@link #compareTrueFirst}. <b>This method is scheduled for deletion 212 * in September 2013.</b> 213 */ 214 @Deprecated 215 public final ComparisonChain compare(boolean left, boolean right) { 216 return compareFalseFirst(left, right); 217 } 218 219 /** 220 * Ends this comparison chain and returns its result: a value having the 221 * same sign as the first nonzero comparison result in the chain, or zero if 222 * every result was zero. 223 */ 224 public abstract int result(); 225}