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