View Javadoc
1   /*
2      Copyright 2011 Atlassian
3   
4      Licensed under the Apache License, Version 2.0 (the "License");
5      you may not use this file except in compliance with the License.
6      You may obtain a copy of the License at
7   
8          http://www.apache.org/licenses/LICENSE-2.0
9   
10     Unless required by applicable law or agreed to in writing, software
11     distributed under the License is distributed on an "AS IS" BASIS,
12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     See the License for the specific language governing permissions and
14     limitations under the License.
15   */
16  package io.atlassian.fugue;
17  
18  import java.io.Serializable;
19  import java.lang.ref.ReferenceQueue;
20  import java.lang.ref.WeakReference;
21  import java.util.Arrays;
22  import java.util.HashMap;
23  import java.util.Map;
24  import java.util.concurrent.ConcurrentHashMap;
25  import java.util.concurrent.ConcurrentMap;
26  import java.util.function.BiFunction;
27  import java.util.function.Consumer;
28  import java.util.function.Function;
29  import java.util.function.Predicate;
30  import java.util.function.Supplier;
31  
32  import static io.atlassian.fugue.Option.option;
33  import static io.atlassian.fugue.Unit.Unit;
34  import static java.util.Objects.requireNonNull;
35  
36  /**
37   * Utility methods for Functions
38   * <P>
39   * Note that this class defines Partial Functions to be functions that return an
40   * {@link io.atlassian.fugue.Option} of the result type, and has some methods
41   * for creating them.
42   *
43   * @since 1.1
44   */
45  public class Functions {
46  
47    // /CLOVER:OFF
48  
49    private Functions() {}
50  
51    // /CLOVER:ON
52    /**
53     * Returns the composition of two functions. For {@code f: A->B} and
54     * {@code g: B->C}, composition is defined as the function h such that
55     * {@code h(a) == g(f(a))} for each {@code a}.
56     *
57     * @param <A> The start type
58     * @param <B> The intermediate type
59     * @param <C> The finished type
60     * @param g the second function to apply, must not be null
61     * @param f the first function to apply, must not be null
62     * @return the composition of {@code f} and {@code g}
63     * @see <a href="//en.wikipedia.org/wiki/Function_composition">function
64     * composition</a>
65     */
66    public static <A, B, C> Function<A, C> compose(final Function<? super B, ? extends C> g, final Function<? super A, ? extends B> f) {
67      return new FunctionComposition<>(g, f);
68    }
69  
70    private static class FunctionComposition<A, B, C> implements Function<A, C>, Serializable {
71      private final Function<? super B, ? extends C> g;
72      private final Function<? super A, ? extends B> f;
73  
74      FunctionComposition(final Function<? super B, ? extends C> g, final Function<? super A, ? extends B> f) {
75        this.g = requireNonNull(g);
76        this.f = requireNonNull(f);
77      }
78  
79      @Override public C apply(final A a) {
80        return g.apply(f.apply(a));
81      }
82  
83      @Override public boolean equals(final Object obj) {
84        if (obj instanceof FunctionComposition) {
85          final FunctionComposition<?, ?, ?> that = (FunctionComposition<?, ?, ?>) obj;
86          return f.equals(that.f) && g.equals(that.g);
87        }
88        return false;
89      }
90  
91      @Override public int hashCode() {
92        return f.hashCode() ^ g.hashCode();
93      }
94  
95      @Override public String toString() {
96        return g.toString() + "(" + f.toString() + ")";
97      }
98  
99      private static final long serialVersionUID = 0;
100   }
101 
102   /**
103    * Performs function application within a higher-order function (applicative
104    * functor pattern).
105    *
106    * @param ca A function to apply within a higher-order function.
107    * @param cab The higher-order function to apply a function to.
108    * @return A new function after applying the given higher-order function to
109    * the given function.
110    * @since 4.0
111    */
112   public static <A, B, C> Function<C, B> ap(final Function<C, A> ca, final Function<C, Function<A, B>> cab) {
113     return m -> ca.andThen(cab.apply(m)).apply(m);
114   }
115 
116   /**
117    * Apply f to each element in elements, with each application using the result
118    * of the previous application as the other argument to f. zero is used as the
119    * first 'result' value. The final result is returned.
120    *
121    * @param <F> the element type
122    * @param <T> the final result type
123    * @param f the function to apply to all the elements
124    * @param zero the starting point for the function
125    * @param elements the series of which each element will be accumulated into a
126    * result
127    * @return the result of accumulating the application of f to all elements
128    * @since 1.1
129    */
130   public static <F, T> T fold(final BiFunction<? super T, F, T> f, final T zero, final Iterable<? extends F> elements) {
131     T currentValue = zero;
132     for (final F element : elements) {
133       currentValue = f.apply(currentValue, element);
134     }
135     return currentValue;
136   }
137 
138   /**
139    * Apply f to each element in elements, with each application using the result
140    * of the previous application as the other argument to f. zero is used as the
141    * first 'result' value. The final result is returned.
142    *
143    * @param <F> the element type
144    * @param <S> the accumulator function input type
145    * @param <T> the return result type
146    * @param f the function to apply to all elements
147    * @param zero the starting point for the function
148    * @param elements the series of which each element will be accumulated into a
149    * result
150    * @return the result of accumulating the application of f to all elements
151    * @since 1.1
152    */
153   public static <F, S, T extends S> T fold(final Function<Pair<S, F>, T> f, final T zero, final Iterable<? extends F> elements) {
154     return fold(toBiFunction(f), zero, elements);
155   }
156 
157   /**
158    * Function that takes another function and applies it to the argument.
159    *
160    * @param <A> the argument and function input type
161    * @param <B> the result type
162    * @param arg the argument that will be applied to any input functions
163    * @return a function that takes a function from A to B , applies the arg and
164    * returns the result
165    * @since 1.1
166    */
167   public static <A, B> Function<Function<A, B>, B> apply(final A arg) {
168     return new Function<Function<A, B>, B>() {
169       @Override public B apply(final Function<A, B> f) {
170         return f.apply(arg);
171       }
172 
173       @Override public String toString() {
174         return "Apply";
175       }
176     };
177   }
178 
179   /**
180    * Function that takes another function and applies it to the argument
181    * supplied by the parameter.
182    *
183    * @param lazyA the supplier of the argument that will be applied to any input
184    * functions
185    * @param <A> the type of the argument supplied, and the function input type
186    * @param <B> the result type of the function
187    * @return a function that takes a function from A to B, applies the argument
188    * from the supplier and returns the result
189    * @since 2.0
190    */
191   public static <A, B> Function<Function<A, B>, B> apply(final Supplier<A> lazyA) {
192     return new Function<Function<A, B>, B>() {
193       @Override public B apply(final Function<A, B> f) {
194         return f.apply(lazyA.get());
195       }
196 
197       @Override public String toString() {
198         return "ApplySupplier";
199       }
200     };
201   }
202 
203   /**
204    * Partial Function that does a type check and matches if the value is of the
205    * right type.
206    *
207    * @param <A> the input type
208    * @param <B> the type we expect it to be
209    * @param cls the type to check against, must not be null
210    * @return a function that returns a Some with the value if of the right type
211    * otherwise a None
212    * @since 1.2
213    */
214   public static <A, B> Function<A, Option<B>> isInstanceOf(final Class<B> cls) {
215     return new InstanceOf<>(cls);
216   }
217 
218   static class InstanceOf<A, B> implements Function<A, Option<B>> {
219     private final Class<B> cls;
220 
221     InstanceOf(final Class<B> cls) {
222       this.cls = requireNonNull(cls);
223     }
224 
225     @Override public Option<B> apply(final A a) {
226       return (cls.isAssignableFrom(a.getClass())) ? Option.some(cls.cast(a)) : Option.<B> none();
227     }
228 
229     @Override public String toString() {
230       return "InstanceOf";
231     }
232 
233     @Override public int hashCode() {
234       return cls.hashCode();
235     }
236 
237     static final long serialVersionUID = 0;
238   }
239 
240   /**
241    * Create a PartialFunction from a {@link java.util.function.Predicate} and a
242    * {@link java.util.function.Function}.
243    *
244    * @param <A> the input type
245    * @param <B> the output type
246    * @param p the predicate to test the value against, must not be null
247    * @param f the function to apply if the predicate passes, must not be null
248    * @return a PartialFunction that tests the supplied predicate before applying
249    * the function.
250    * @since 1.2
251    */
252   public static <A, B> Function<A, Option<B>> partial(final Predicate<? super A> p, final Function<? super A, ? extends B> f) {
253     return new Partial<>(p, f);
254   }
255 
256   static class Partial<A, B> implements Function<A, Option<B>> {
257     private final Predicate<? super A> p;
258     private final Function<? super A, ? extends B> f;
259 
260     Partial(final Predicate<? super A> p, final Function<? super A, ? extends B> f) {
261       this.p = requireNonNull(p);
262       this.f = requireNonNull(f);
263     }
264 
265     @Override public Option<B> apply(final A a) {
266       return (p.test(a)) ? option(f.apply(a)) : Option.<B> none();
267     }
268 
269     @Override public String toString() {
270       return "Partial";
271     }
272 
273     @Override public int hashCode() {
274       return f.hashCode() ^ p.hashCode();
275     }
276   }
277 
278   /**
279    * Compose two PartialFunctions into one.
280    * <p>
281    * Kleisli composition. In Haskell it is defined as <code>&gt;=&gt;</code>,
282    * AKA <a href="http://stackoverflow.com/a/7833488/210216">
283    * "compose, fishy, compose"</a>
284    *
285    * @param <A> the input type
286    * @param <B> the middle type
287    * @param <C> the output type
288    * @param bc partial function from {@code B -> C}, must not be null
289    * @param ab partial function from {@code A -> B}, must not be null
290    * @return a PartialFunction that flatMaps g on to the result of applying f.
291    * @since 1.2
292    */
293   public static <A, B, C> Function<A, Option<C>> composeOption(final Function<? super B, ? extends Option<? extends C>> bc,
294     final Function<? super A, ? extends Option<? extends B>> ab) {
295     return new PartialComposer<>(ab, bc);
296   }
297 
298   static class PartialComposer<A, B, C> implements Function<A, Option<C>> {
299     private final Function<? super A, ? extends Option<? extends B>> ab;
300     private final Function<? super B, ? extends Option<? extends C>> bc;
301 
302     PartialComposer(final Function<? super A, ? extends Option<? extends B>> ab, final Function<? super B, ? extends Option<? extends C>> bc) {
303       this.ab = requireNonNull(ab);
304       this.bc = requireNonNull(bc);
305     }
306 
307     @Override public Option<C> apply(final A a) {
308       return ab.apply(a).flatMap(bc);
309     }
310 
311     @Override public String toString() {
312       return "PartialComposer";
313     }
314 
315     @Override public int hashCode() {
316       return bc.hashCode() ^ ab.hashCode();
317     }
318   }
319 
320   /**
321    * Converts a function that takes a pair of arguments to a function that takes
322    * two arguments
323    *
324    * @param <A> the type of the left of the pair
325    * @param <B> the type of the right of the pair
326    * @param <C> the result type
327    * @param fpair the source function that takes a pair of arguments, must not
328    * be null
329    * @return a function that takes two arguments
330    * @since 2.0
331    */
332   public static <A, B, C> BiFunction<A, B, C> toBiFunction(final Function<Pair<A, B>, C> fpair) {
333     requireNonNull(fpair);
334     return new BiFunction<A, B, C>() {
335       @Override public C apply(final A a, final B b) {
336         return fpair.apply(Pair.pair(a, b));
337       }
338 
339       @Override public String toString() {
340         return "ToBiFunction";
341       }
342     };
343   }
344 
345   /**
346    * Transforms a function that takes 2 arguments into a function that takes the
347    * first argument and return a new function that takes the second argument and
348    * return the final result.
349    *
350    * @param <A> the type of the first argument
351    * @param <B> the type of the second argument
352    * @param <C> the type of the final result
353    * @param f2 the original function that takes 2 arguments, must not be null
354    * @return the curried form of the original function
355    * @since 2.0
356    */
357   public static <A, B, C> Function<A, Function<B, C>> curried(final BiFunction<A, B, C> f2) {
358     requireNonNull(f2);
359     return new CurriedFunction<>(f2);
360   }
361 
362   private static class CurriedFunction<A, B, C> implements Function<A, Function<B, C>> {
363     private final BiFunction<A, B, C> f2;
364 
365     CurriedFunction(final BiFunction<A, B, C> f2) {
366       this.f2 = f2;
367     }
368 
369     @Override public Function<B, C> apply(final A a) {
370       return b -> f2.apply(a, b);
371     }
372 
373     @Override public String toString() {
374       return "CurriedFunction";
375     }
376 
377     @Override public int hashCode() {
378       return f2.hashCode();
379     }
380   }
381 
382   /**
383    * Transforms a function from {@code A -> (B -> C)} into a function from
384    * {@code B -> (A -> C)}.
385    *
386    * @param <A> the type of the first argument
387    * @param <B> the type of the second argument
388    * @param <C> the type of the final result
389    * @param f2 the original function from {@code A -> (B -> C)}, must not be
390    * null
391    * @return the flipped form of the original function
392    * @since 2.0
393    */
394   public static <A, B, C> Function<B, Function<A, C>> flip(final Function<A, Function<B, C>> f2) {
395     requireNonNull(f2);
396     return new FlippedFunction<>(f2);
397   }
398 
399   private static class FlippedFunction<A, B, C> implements Function<B, Function<A, C>> {
400     private final Function<A, Function<B, C>> f2;
401 
402     FlippedFunction(final Function<A, Function<B, C>> f2) {
403       this.f2 = f2;
404     }
405 
406     @Override public Function<A, C> apply(final B b) {
407       return a -> f2.apply(a).apply(b);
408     }
409 
410     @Override public String toString() {
411       return "FlippedFunction";
412     }
413 
414     @Override public int hashCode() {
415       return f2.hashCode();
416     }
417   }
418 
419   /**
420    * Maps a function that returns nulls into a Partial function that returns an
421    * Option of the result.
422    *
423    * @param <A> the input type
424    * @param <B> the output type
425    * @param f the function that may return nulls
426    * @return a function that converts any nulls into Options
427    * @since 2.0
428    */
429   public static <A, B> Function<A, Option<B>> mapNullToOption(final Function<? super A, ? extends B> f) {
430     return Functions.compose(Functions.<B> nullToOption(), f);
431   }
432 
433   /**
434    * Function that turns null inputs into a none, and not-null inputs into some.
435    *
436    * @param <A> the input type
437    * @return a function that never returns nulls.
438    * @since 2.2.1
439    */
440   public static <A> Function<A, Option<A>> nullToOption() {
441     return Options.toOption();
442   }
443 
444   /**
445    * Takes a Function and memoizes (caches) the result for each input. This
446    * memoization is weak, so it shouldn't leak memory on its own, but equally it
447    * may expunge entries if no-one else is holding the reference in the
448    * meantime.
449    * <p>
450    * NOTE: it is very important that the docs on the input type are read
451    * carefully. Failure to heed adhere to this will lead to unspecified behavior
452    * (bugs!)
453    *
454    * @param <A> the input type, like any cache, this type should be a value,
455    * that is it should be immutable and have correct hashcode and equals
456    * implementations.
457    * @param <B> the output type
458    * @param f the function who's output will be memoized, must not be null
459    * @return a function that memoizes the results of the function using the
460    * input as a weak key
461    * @since 2.2
462    */
463   public static <A, B> Function<A, B> weakMemoize(final Function<A, B> f) {
464     return WeakMemoizer.weakMemoizer(f);
465   }
466 
467   /**
468    * Get a function that uses the Supplier as a factory for all inputs.
469    *
470    * @param <D> the key type, ignored
471    * @param <R> the result type
472    * @param supplier called for all inputs, must not be null
473    * @return the function
474    *
475    * @since 2.2
476    */
477   static <D, R> Function<D, R> fromSupplier(final Supplier<R> supplier) {
478     return new FromSupplier<>(supplier);
479   }
480 
481   static class FromSupplier<D, R> implements Function<D, R> {
482     private final Supplier<R> supplier;
483 
484     FromSupplier(final Supplier<R> supplier) {
485       this.supplier = requireNonNull(supplier, "supplier");
486     }
487 
488     @Override public R apply(final D ignore) {
489       return supplier.get();
490     }
491 
492     @Override public String toString() {
493       return "FromSupplier";
494     }
495 
496     @Override public int hashCode() {
497       return supplier.hashCode();
498     }
499   }
500 
501   /**
502    * Get a function (with {@link Unit} return type) that calls the consumer for
503    * all inputs.
504    *
505    * @param <D> the key type
506    * @param consumer called for all inputs, must not be null
507    * @return the function
508    * @since 4.4.0
509    */
510   public static <D> Function<D, Unit> fromConsumer(Consumer<D> consumer) {
511     return new FromConsumer<>(consumer);
512   }
513 
514   private static class FromConsumer<D> implements Function<D, Unit> {
515     private final Consumer<D> consumer;
516 
517     FromConsumer(final Consumer<D> consumer) {
518       this.consumer = requireNonNull(consumer);
519     }
520 
521     @Override public Unit apply(D d) {
522       consumer.accept(d);
523       return Unit();
524     }
525 
526     @Override public String toString() {
527       return "FromConsumer";
528     }
529 
530     @Override public int hashCode() {
531       return consumer.hashCode();
532     }
533   }
534 
535   /**
536    * Returns the identity function. Consider using
537    * {@link java.util.function.Function#identity()}
538    *
539    * @return a {@link java.util.function.Function} that retruns it's input.
540    * @param <A> a A object.
541    */
542   @SuppressWarnings("unchecked") public static <A> Function<A, A> identity() {
543     // cast a singleton Function<Object, Object> to a more useful type
544     return (Function<A, A>) IdentityFunction.INSTANCE;
545   }
546 
547   // enum singleton pattern
548   private enum IdentityFunction implements Function<Object, Object> {
549     INSTANCE;
550 
551     @Override public Object apply(final Object o) {
552       return o;
553     }
554 
555     @Override public String toString() {
556       return "identity";
557     }
558   }
559 
560   /**
561    * Create a function ignores it's input an produces a constant value
562    *
563    * @param constant value to return
564    * @param <A> type of the ignored input
565    * @param <B> type of the constant returned
566    * @return a function producing a constant value
567    */
568   public static <A, B> Function<A, B> constant(final B constant) {
569     return from -> constant;
570   }
571 
572   /**
573    * Create a function that performs a map lookup returning None for null
574    *
575    * If you do not need a nondefaulted return result using a method reference is
576    * preferred {@literal map::get}
577    *
578    * @param map map to use for lookup
579    * @param <A> map key type
580    * @param <B> map value type
581    * @return result of calling Map#get replacing null with none
582    * @see Functions#forMapWithDefault to supply a default value for none
583    */
584   public static <A, B> Function<A, Option<B>> forMap(final Map<A, B> map) {
585     return a -> option(map.get(a));
586   }
587 
588   /**
589    * Create a function that performs a map lookup supplying a default value when
590    * a Map#get returns null
591    *
592    * If you do not need a defaulted return result using a method reference is
593    * preferred {@literal map::get}
594    *
595    * @param map map to use for lookup
596    * @param <A> map key type
597    * @param <B> map value type
598    * @return result of calling Map#get returning defaultValue instead if the
599    * result was null
600    * @param defaultValue a B to use when the map returns null from Map#get.
601    */
602   public static <A, B> Function<A, B> forMapWithDefault(final Map<A, B> map, final B defaultValue) {
603     return forMap(map).andThen(o -> o.getOrElse(defaultValue));
604   }
605 
606   /**
607    * Creates a stack of matcher functions and returns the first result that
608    * matches.
609    *
610    * @param <A> the input type
611    * @param <B> the output type
612    * @param f1 partial function, tried in order.
613    * @param f2 partial function, tried in order.
614    * @return a PartialFunction that composes all the functions and tries each
615    * one in sequence.
616    * @since 1.2
617    */
618   public static <A, B> Function<A, Option<B>> matches(final Function<? super A, ? extends Option<? extends B>> f1,
619     final Function<? super A, ? extends Option<? extends B>> f2) {
620     return matcher(f1, f2);
621   }
622 
623   /**
624    * Creates a stack of matcher functions and returns the first result that
625    * matches.
626    *
627    * @param <A> the input type
628    * @param <B> the output type
629    * @param f1 partial function, tried in order.
630    * @param f2 partial function, tried in order.
631    * @param f3 partial function, tried in order.
632    * @return a PartialFunction that composes all the functions and tries each
633    * one in sequence.
634    * @since 1.2
635    */
636   public static <A, B> Function<A, Option<B>> matches(final Function<? super A, ? extends Option<? extends B>> f1,
637     final Function<? super A, ? extends Option<? extends B>> f2, final Function<? super A, ? extends Option<? extends B>> f3) {
638     return matcher(f1, f2, f3);
639   }
640 
641   /**
642    * Creates a stack of matcher functions and returns the first result that
643    * matches.
644    *
645    * @param <A> the input type
646    * @param <B> the output type
647    * @param f1 partial function, tried in order.
648    * @param f2 partial function, tried in order.
649    * @param f3 partial function, tried in order.
650    * @param f4 partial function, tried in order.
651    * @return a PartialFunction that composes all the functions and tries each
652    * one in sequence.
653    * @since 1.2
654    */
655   public static <A, B> Function<A, Option<B>> matches(final Function<? super A, ? extends Option<? extends B>> f1,
656     final Function<? super A, ? extends Option<? extends B>> f2, final Function<? super A, ? extends Option<? extends B>> f3,
657     final Function<? super A, ? extends Option<? extends B>> f4) {
658     return new Matcher<>(Arrays.<Function<? super A, ? extends Option<? extends B>>> asList(f1, f2, f3, f4));
659   }
660 
661   /**
662    * Creates a stack of matcher functions and returns the first result that
663    * matches.
664    *
665    * @param <A> the input type
666    * @param <B> the output type
667    * @param f1 partial function, tried in order.
668    * @param f2 partial function, tried in order.
669    * @param f3 partial function, tried in order.
670    * @param f4 partial function, tried in order.
671    * @param f5 partial function, tried in order.
672    * @param fs partial functions, tried in order.
673    * @return a PartialFunction that composes all the functions and tries each
674    * one in sequence.
675    * @since 1.2
676    */
677   @SafeVarargs public static <A, B> Function<A, Option<B>> matches(final Function<? super A, ? extends Option<? extends B>> f1,
678     final Function<? super A, ? extends Option<? extends B>> f2, final Function<? super A, ? extends Option<? extends B>> f3,
679     final Function<? super A, ? extends Option<? extends B>> f4, final Function<? super A, ? extends Option<? extends B>> f5,
680     final Function<? super A, ? extends Option<? extends B>>... fs) {
681 
682     @SuppressWarnings("unchecked")
683     final Function<? super A, ? extends Option<? extends B>>[] matchingFunctions = new Function[5 + fs.length];
684     matchingFunctions[0] = f1;
685     matchingFunctions[1] = f2;
686     matchingFunctions[2] = f3;
687     matchingFunctions[3] = f4;
688     matchingFunctions[4] = f5;
689     System.arraycopy(fs, 0, matchingFunctions, 5, fs.length);
690 
691     return new Matcher<>(Arrays.asList(matchingFunctions));
692   }
693 
694   /* utility copy function */
695   @SafeVarargs private static <A, B> Matcher<A, B> matcher(final Function<? super A, ? extends Option<? extends B>>... fs) {
696     @SuppressWarnings("unchecked")
697     final Function<? super A, ? extends Option<? extends B>>[] dest = new Function[fs.length];
698 
699     System.arraycopy(fs, 0, dest, 0, fs.length);
700     for (final Function<? super A, ? extends Option<? extends B>> f : fs) {
701       if (f == null) {
702         throw new NullPointerException("function value was null");
703       }
704     }
705 
706     return new Matcher<>(Arrays.asList(dest));
707   }
708 
709   static class Matcher<A, B> implements Function<A, Option<B>> {
710     private final Iterable<Function<? super A, ? extends Option<? extends B>>> fs;
711 
712     Matcher(final Iterable<Function<? super A, ? extends Option<? extends B>>> fs) {
713       this.fs = requireNonNull(fs);
714 
715       if (!fs.iterator().hasNext()) {
716         throw new IllegalArgumentException("Condition must be true but returned false instead");
717       }
718     }
719 
720     @Override public Option<B> apply(final A a) {
721       for (final Function<? super A, ? extends Option<? extends B>> f : fs) {
722         @SuppressWarnings("unchecked")
723         final Option<B> b = (Option<B>) f.apply(a);
724         if (b.isDefined())
725           return b;
726       }
727       return Option.none();
728     }
729 
730     @Override public String toString() {
731       return "Matcher";
732     }
733 
734     @Override public int hashCode() {
735       return fs.hashCode();
736     }
737   }
738 
739   /**
740    * Class supports the implementation of
741    * {@link Functions#weakMemoize(Function)} and is not intended for general
742    * use.
743    *
744    * {@link WeakMemoizer} caches the result of another function. The result is
745    * {@link WeakReference weakly referenced} internally. This is useful if the
746    * result is expensive to compute or the identity of the result is
747    * particularly important.
748    * <p>
749    * If the results from this function are further cached then they will tend to
750    * stay in this cache for longer.
751    *
752    * @param <A> comparable descriptor, the usual rules for any {@link HashMap}
753    * key apply.
754    * @param <B> the value
755    */
756   static final class WeakMemoizer<A, B> implements Function<A, B> {
757     static <A, B> WeakMemoizer<A, B> weakMemoizer(final Function<A, B> delegate) {
758       return new WeakMemoizer<>(delegate);
759     }
760 
761     private final ConcurrentMap<A, MappedReference<A, B>> map;
762     private final ReferenceQueue<B> queue = new ReferenceQueue<>();
763     private final Function<A, B> delegate;
764 
765     /**
766      * Construct a new {@link WeakMemoizer} instance.
767      *
768      * @param delegate for creating the initial values.
769      */
770     WeakMemoizer(final Function<A, B> delegate) {
771       this.map = new ConcurrentHashMap<>();
772       this.delegate = requireNonNull(delegate, "delegate");
773     }
774 
775     /**
776      * Get a result for the supplied Descriptor.
777      *
778      * @param descriptor must not be null
779      * @return descriptor lock
780      */
781     @Override public B apply(final A descriptor) {
782       expungeStaleEntries();
783       requireNonNull(descriptor, "descriptor");
784       while (true) {
785         final MappedReference<A, B> reference = map.get(descriptor);
786         if (reference != null) {
787           final B value = reference.get();
788           if (value != null) {
789             return value;
790           }
791           map.remove(descriptor, reference);
792         }
793         map.putIfAbsent(descriptor, new MappedReference<>(descriptor, delegate.apply(descriptor), queue));
794       }
795     }
796 
797     // expunge entries whose value reference has been collected
798     @SuppressWarnings("unchecked") private void expungeStaleEntries() {
799       MappedReference<A, B> ref;
800       // /CLOVER:OFF
801       while ((ref = (MappedReference<A, B>) queue.poll()) != null) {
802         final A key = ref.getDescriptor();
803         if (key == null) {
804           // DO NOT REMOVE! In theory this should not be necessary as it
805           // should not be able to be null - but we have seen it happen!
806           continue;
807         }
808         map.remove(key, ref);
809       }
810       // /CLOVER:ON
811     }
812 
813     /**
814      * A weak reference that maintains a reference to the key so that it can be
815      * removed from the map when the value is garbage collected.
816      */
817     static final class MappedReference<K, V> extends WeakReference<V> {
818       private final K key;
819 
820       public MappedReference(final K key, final V value, final ReferenceQueue<? super V> q) {
821         super(requireNonNull(value, "value"), q);
822         this.key = requireNonNull(key, "key");
823       }
824 
825       final K getDescriptor() {
826         return key;
827       }
828     }
829   }
830 
831   static <A> Predicate<A> countingPredicate(final int n) {
832     if (n < 0) {
833       throw new IllegalArgumentException("n must be positive");
834     }
835     return new Predicate<A>() {
836       int count = n;
837 
838       @Override public boolean test(final A a) {
839         return --count >= 0;
840       }
841     };
842   }
843 }