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