001/* 002 * Copyright (C) 2007 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 005 * in compliance with the License. You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software distributed under the License 010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 011 * or implied. See the License for the specific language governing permissions and limitations under 012 * the License. 013 */ 014 015package com.google.common.base; 016 017import static com.google.common.base.NullnessCasts.uncheckedCastNullableTToT; 018import static com.google.common.base.Preconditions.checkArgument; 019import static com.google.common.base.Preconditions.checkNotNull; 020 021import com.google.common.annotations.GwtCompatible; 022import java.io.Serializable; 023import java.util.Map; 024import javax.annotation.CheckForNull; 025import org.checkerframework.checker.nullness.qual.Nullable; 026 027/** 028 * Static utility methods pertaining to {@code com.google.common.base.Function} instances; see that 029 * class for information about migrating to {@code java.util.function}. 030 * 031 * <p>All methods return serializable functions as long as they're given serializable parameters. 032 * 033 * <p>See the Guava User Guide article on <a 034 * href="https://github.com/google/guava/wiki/FunctionalExplained">the use of {@code Function}</a>. 035 * 036 * @author Mike Bostock 037 * @author Jared Levy 038 * @since 2.0 039 */ 040@GwtCompatible 041@ElementTypesAreNonnullByDefault 042public final class Functions { 043 private Functions() {} 044 045 /** 046 * A function equivalent to the method reference {@code Object::toString}, for users not yet using 047 * Java 8. The function simply invokes {@code toString} on its argument and returns the result. It 048 * throws a {@link NullPointerException} on null input. 049 * 050 * <p><b>Warning:</b> The returned function may not be <i>consistent with equals</i> (as 051 * documented at {@link Function#apply}). For example, this function yields different results for 052 * the two equal instances {@code ImmutableSet.of(1, 2)} and {@code ImmutableSet.of(2, 1)}. 053 * 054 * <p><b>Warning:</b> as with all function types in this package, avoid depending on the specific 055 * {@code equals}, {@code hashCode} or {@code toString} behavior of the returned function. A 056 * future migration to {@code java.util.function} will not preserve this behavior. 057 * 058 * <p><b>For Java 8 users:</b> use the method reference {@code Object::toString} instead. In the 059 * future, when this class requires Java 8, this method will be deprecated. See {@link Function} 060 * for more important information about the Java 8 transition. 061 */ 062 public static Function<Object, String> toStringFunction() { 063 return ToStringFunction.INSTANCE; 064 } 065 066 // enum singleton pattern 067 private enum ToStringFunction implements Function<Object, String> { 068 INSTANCE; 069 070 @Override 071 public String apply(Object o) { 072 checkNotNull(o); // eager for GWT. 073 return o.toString(); 074 } 075 076 @Override 077 public String toString() { 078 return "Functions.toStringFunction()"; 079 } 080 } 081 082 /** Returns the identity function. */ 083 // implementation is "fully variant"; E has become a "pass-through" type 084 @SuppressWarnings("unchecked") 085 public static <E extends @Nullable Object> Function<E, E> identity() { 086 return (Function<E, E>) IdentityFunction.INSTANCE; 087 } 088 089 // enum singleton pattern 090 private enum IdentityFunction implements Function<@Nullable Object, @Nullable Object> { 091 INSTANCE; 092 093 @Override 094 @CheckForNull 095 public Object apply(@CheckForNull Object o) { 096 return o; 097 } 098 099 @Override 100 public String toString() { 101 return "Functions.identity()"; 102 } 103 } 104 105 /** 106 * Returns a function which performs a map lookup. The returned function throws an {@link 107 * IllegalArgumentException} if given a key that does not exist in the map. See also {@link 108 * #forMap(Map, Object)}, which returns a default value in this case. 109 * 110 * <p>Note: if {@code map} is a {@link com.google.common.collect.BiMap BiMap} (or can be one), you 111 * can use {@link com.google.common.collect.Maps#asConverter Maps.asConverter} instead to get a 112 * function that also supports reverse conversion. 113 * 114 * <p><b>Java 8 users:</b> if you are okay with {@code null} being returned for an unrecognized 115 * key (instead of an exception being thrown), you can use the method reference {@code map::get} 116 * instead. 117 */ 118 public static <K extends @Nullable Object, V extends @Nullable Object> Function<K, V> forMap( 119 Map<K, V> map) { 120 return new FunctionForMapNoDefault<>(map); 121 } 122 123 /** 124 * Returns a function which performs a map lookup with a default value. The function created by 125 * this method returns {@code defaultValue} for all inputs that do not belong to the map's key 126 * set. See also {@link #forMap(Map)}, which throws an exception in this case. 127 * 128 * <p><b>Java 8 users:</b> you can just write the lambda expression {@code k -> 129 * map.getOrDefault(k, defaultValue)} instead. 130 * 131 * @param map source map that determines the function behavior 132 * @param defaultValue the value to return for inputs that aren't map keys 133 * @return function that returns {@code map.get(a)} when {@code a} is a key, or {@code 134 * defaultValue} otherwise 135 */ 136 public static <K extends @Nullable Object, V extends @Nullable Object> Function<K, V> forMap( 137 Map<K, ? extends V> map, @ParametricNullness V defaultValue) { 138 return new ForMapWithDefault<>(map, defaultValue); 139 } 140 141 private static class FunctionForMapNoDefault< 142 K extends @Nullable Object, V extends @Nullable Object> 143 implements Function<K, V>, Serializable { 144 final Map<K, V> map; 145 146 FunctionForMapNoDefault(Map<K, V> map) { 147 this.map = checkNotNull(map); 148 } 149 150 @Override 151 @ParametricNullness 152 public V apply(@ParametricNullness K key) { 153 V result = map.get(key); 154 checkArgument(result != null || map.containsKey(key), "Key '%s' not present in map", key); 155 // The unchecked cast is safe because of the containsKey check. 156 return uncheckedCastNullableTToT(result); 157 } 158 159 @Override 160 public boolean equals(@CheckForNull Object o) { 161 if (o instanceof FunctionForMapNoDefault) { 162 FunctionForMapNoDefault<?, ?> that = (FunctionForMapNoDefault<?, ?>) o; 163 return map.equals(that.map); 164 } 165 return false; 166 } 167 168 @Override 169 public int hashCode() { 170 return map.hashCode(); 171 } 172 173 @Override 174 public String toString() { 175 return "Functions.forMap(" + map + ")"; 176 } 177 178 private static final long serialVersionUID = 0; 179 } 180 181 private static class ForMapWithDefault<K extends @Nullable Object, V extends @Nullable Object> 182 implements Function<K, V>, Serializable { 183 final Map<K, ? extends V> map; 184 @ParametricNullness final V defaultValue; 185 186 ForMapWithDefault(Map<K, ? extends V> map, @ParametricNullness V defaultValue) { 187 this.map = checkNotNull(map); 188 this.defaultValue = defaultValue; 189 } 190 191 @Override 192 @ParametricNullness 193 public V apply(@ParametricNullness K key) { 194 V result = map.get(key); 195 // The unchecked cast is safe because of the containsKey check. 196 return (result != null || map.containsKey(key)) 197 ? uncheckedCastNullableTToT(result) 198 : defaultValue; 199 } 200 201 @Override 202 public boolean equals(@CheckForNull Object o) { 203 if (o instanceof ForMapWithDefault) { 204 ForMapWithDefault<?, ?> that = (ForMapWithDefault<?, ?>) o; 205 return map.equals(that.map) && Objects.equal(defaultValue, that.defaultValue); 206 } 207 return false; 208 } 209 210 @Override 211 public int hashCode() { 212 return Objects.hashCode(map, defaultValue); 213 } 214 215 @Override 216 public String toString() { 217 // TODO(cpovirk): maybe remove "defaultValue=" to make this look like the method call does 218 return "Functions.forMap(" + map + ", defaultValue=" + defaultValue + ")"; 219 } 220 221 private static final long serialVersionUID = 0; 222 } 223 224 /** 225 * Returns the composition of two functions. For {@code f: A->B} and {@code g: B->C}, composition 226 * is defined as the function h such that {@code h(a) == g(f(a))} for each {@code a}. 227 * 228 * <p><b>Java 8 users:</b> use {@code g.compose(f)} or (probably clearer) {@code f.andThen(g)} 229 * instead. 230 * 231 * @param g the second function to apply 232 * @param f the first function to apply 233 * @return the composition of {@code f} and {@code g} 234 * @see <a href="//en.wikipedia.org/wiki/Function_composition">function composition</a> 235 */ 236 public static <A extends @Nullable Object, B extends @Nullable Object, C extends @Nullable Object> 237 Function<A, C> compose(Function<B, C> g, Function<A, ? extends B> f) { 238 return new FunctionComposition<>(g, f); 239 } 240 241 private static class FunctionComposition< 242 A extends @Nullable Object, B extends @Nullable Object, C extends @Nullable Object> 243 implements Function<A, C>, Serializable { 244 private final Function<B, C> g; 245 private final Function<A, ? extends B> f; 246 247 public FunctionComposition(Function<B, C> g, Function<A, ? extends B> f) { 248 this.g = checkNotNull(g); 249 this.f = checkNotNull(f); 250 } 251 252 @Override 253 @ParametricNullness 254 public C apply(@ParametricNullness A a) { 255 return g.apply(f.apply(a)); 256 } 257 258 @Override 259 public boolean equals(@CheckForNull Object obj) { 260 if (obj instanceof FunctionComposition) { 261 FunctionComposition<?, ?, ?> that = (FunctionComposition<?, ?, ?>) obj; 262 return f.equals(that.f) && g.equals(that.g); 263 } 264 return false; 265 } 266 267 @Override 268 public int hashCode() { 269 return f.hashCode() ^ g.hashCode(); 270 } 271 272 @Override 273 public String toString() { 274 // TODO(cpovirk): maybe make this look like the method call does ("Functions.compose(...)") 275 return g + "(" + f + ")"; 276 } 277 278 private static final long serialVersionUID = 0; 279 } 280 281 /** 282 * Creates a function that returns the same boolean output as the given predicate for all inputs. 283 * 284 * <p>The returned function is <i>consistent with equals</i> (as documented at {@link 285 * Function#apply}) if and only if {@code predicate} is itself consistent with equals. 286 * 287 * <p><b>Java 8 users:</b> use the method reference {@code predicate::test} instead. 288 */ 289 public static <T extends @Nullable Object> Function<T, Boolean> forPredicate( 290 Predicate<T> predicate) { 291 return new PredicateFunction<T>(predicate); 292 } 293 294 /** @see Functions#forPredicate */ 295 private static class PredicateFunction<T extends @Nullable Object> 296 implements Function<T, Boolean>, Serializable { 297 private final Predicate<T> predicate; 298 299 private PredicateFunction(Predicate<T> predicate) { 300 this.predicate = checkNotNull(predicate); 301 } 302 303 @Override 304 public Boolean apply(@ParametricNullness T t) { 305 return predicate.apply(t); 306 } 307 308 @Override 309 public boolean equals(@CheckForNull Object obj) { 310 if (obj instanceof PredicateFunction) { 311 PredicateFunction<?> that = (PredicateFunction<?>) obj; 312 return predicate.equals(that.predicate); 313 } 314 return false; 315 } 316 317 @Override 318 public int hashCode() { 319 return predicate.hashCode(); 320 } 321 322 @Override 323 public String toString() { 324 return "Functions.forPredicate(" + predicate + ")"; 325 } 326 327 private static final long serialVersionUID = 0; 328 } 329 330 /** 331 * Returns a function that ignores its input and always returns {@code value}. 332 * 333 * <p><b>Java 8 users:</b> use the lambda expression {@code o -> value} instead. 334 * 335 * @param value the constant value for the function to return 336 * @return a function that always returns {@code value} 337 */ 338 public static <E extends @Nullable Object> Function<@Nullable Object, E> constant( 339 @ParametricNullness E value) { 340 return new ConstantFunction<>(value); 341 } 342 343 private static class ConstantFunction<E extends @Nullable Object> 344 implements Function<@Nullable Object, E>, Serializable { 345 @ParametricNullness private final E value; 346 347 public ConstantFunction(@ParametricNullness E value) { 348 this.value = value; 349 } 350 351 @Override 352 @ParametricNullness 353 public E apply(@CheckForNull Object from) { 354 return value; 355 } 356 357 @Override 358 public boolean equals(@CheckForNull Object obj) { 359 if (obj instanceof ConstantFunction) { 360 ConstantFunction<?> that = (ConstantFunction<?>) obj; 361 return Objects.equal(value, that.value); 362 } 363 return false; 364 } 365 366 @Override 367 public int hashCode() { 368 return (value == null) ? 0 : value.hashCode(); 369 } 370 371 @Override 372 public String toString() { 373 return "Functions.constant(" + value + ")"; 374 } 375 376 private static final long serialVersionUID = 0; 377 } 378 379 /** 380 * Returns a function that ignores its input and returns the result of {@code supplier.get()}. 381 * 382 * <p><b>Java 8 users:</b> use the lambda expression {@code o -> supplier.get()} instead. 383 * 384 * @since 10.0 385 */ 386 public static <F extends @Nullable Object, T extends @Nullable Object> Function<F, T> forSupplier( 387 Supplier<T> supplier) { 388 return new SupplierFunction<>(supplier); 389 } 390 391 /** @see Functions#forSupplier */ 392 private static class SupplierFunction<F extends @Nullable Object, T extends @Nullable Object> 393 implements Function<F, T>, Serializable { 394 395 private final Supplier<T> supplier; 396 397 private SupplierFunction(Supplier<T> supplier) { 398 this.supplier = checkNotNull(supplier); 399 } 400 401 @Override 402 @ParametricNullness 403 public T apply(@ParametricNullness F input) { 404 return supplier.get(); 405 } 406 407 @Override 408 public boolean equals(@CheckForNull Object obj) { 409 if (obj instanceof SupplierFunction) { 410 SupplierFunction<?, ?> that = (SupplierFunction<?, ?>) obj; 411 return this.supplier.equals(that.supplier); 412 } 413 return false; 414 } 415 416 @Override 417 public int hashCode() { 418 return supplier.hashCode(); 419 } 420 421 @Override 422 public String toString() { 423 return "Functions.forSupplier(" + supplier + ")"; 424 } 425 426 private static final long serialVersionUID = 0; 427 } 428}