Advertisement
DulcetAirman

ToOptional

Jan 11th, 2016
116
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package ch.claude_martin.common;
  2.  
  3. import java.util.Collection;
  4. import java.util.Collections;
  5. import java.util.Optional;
  6. import java.util.Set;
  7. import java.util.function.BiConsumer;
  8. import java.util.function.BinaryOperator;
  9. import java.util.function.Function;
  10. import java.util.function.Supplier;
  11. import java.util.stream.Collector;
  12. import java.util.stream.Collectors;
  13. import java.util.stream.Stream;
  14.  
  15. import ch.claude_martin.common.ToOptional.Ref;
  16.  
  17. /**
  18.  * Collects a single element from a stream into an {@link Optional}. The returned Optional is empty if
  19.  * there is not exactly one element in the stream.
  20.  *
  21.  * <p>
  22.  * This is an alternative to {@link Stream#findAny()} as it checks that there is exactly one element
  23.  * in the stream that can be <i>found</i>. It can also be seen as an alternative to the
  24.  * {@link Collectors}, as this uses an Optional like a {@link Collection}, similar to
  25.  * {@link Collectors#toList()}.
  26.  * </p>
  27.  *
  28.  * <p>
  29.  * Note that this might take a long time for streams with many elements.
  30.  * </p>
  31.  *
  32.  * <pre>
  33.  * Example:
  34.  * List&lt;Integer> list = Arrays.asList(1,2,3,4);
  35.  * Optional&lt;Integer> o = list.stream().filter(i->i==3).collect(ToOptional.get());
  36.  * System.out.println(o); // Optional[3]
  37.  * o = list.stream().filter(i->i>0).collect(ToOptional.get());
  38.  * System.out.println(o); // Optional.empty
  39.  * </pre>
  40.  *
  41.  * @see Collectors
  42.  * @param <T>
  43.  *          Type of the expected element.
  44.  */
  45. public final class ToOptional<T> implements Collector<T, Ref<T>, Optional<T>> {
  46.   private ToOptional() {
  47.     super();
  48.   }
  49.  
  50.   public final static ToOptional<?> INSTANCE = new ToOptional<>();
  51.  
  52.   /**
  53.    * Returns an instance of {@link ToOptional}.
  54.    * <p>
  55.    * Note: This always returns the same {@link Collector}.
  56.    */
  57.   @SuppressWarnings("unchecked")
  58.   public static <T> ToOptional<T> get() {
  59.     return (ToOptional<T>) INSTANCE;
  60.   }
  61.  
  62.   static class Ref<RT> {
  63.     private RT value;
  64.     private int count = 0;
  65.  
  66.     public void set(RT value) {
  67.       this.value = value;
  68.       this.count++;
  69.     }
  70.  
  71.     public RT get() {
  72.       return this.value;
  73.     }
  74.  
  75.     public int getCount() {
  76.       return this.count;
  77.     }
  78.   }
  79.  
  80.   @Override
  81.   public Supplier<Ref<T>> supplier() {
  82.     return Ref<T>::new;
  83.   }
  84.  
  85.   @Override
  86.   public BiConsumer<Ref<T>, T> accumulator() {
  87.     return (ref, value) -> {
  88.       ref.set(value);
  89.     };
  90.   }
  91.  
  92.   @Override
  93.   public BinaryOperator<Ref<T>> combiner() {
  94.     return (ref1, ref2) -> {
  95.       if (ref1.getCount() == 0)
  96.         return ref2;
  97.       if (ref2.getCount() == 0)
  98.         return ref1;
  99.       ref1.set(null);// increments count
  100.       return ref1;
  101.     };
  102.   }
  103.  
  104.   @Override
  105.   public Function<Ref<T>, Optional<T>> finisher() {
  106.     return (ref) -> {
  107.       if (ref.getCount() != 1)
  108.         return Optional.empty();
  109.       return Optional.ofNullable(ref.get());
  110.     };
  111.   }
  112.  
  113.   @Override
  114.   public Set<java.util.stream.Collector.Characteristics> characteristics() {
  115.     return Collections.emptySet();
  116.   }
  117.  
  118. }
Advertisement
Advertisement
Advertisement
RAW Paste Data Copied
Advertisement