DulcetAirman icon

ToOptional

DulcetAirman | PRO | 01/11/16 07:07:06 PM UTC | 0 ⭐ | 882 👁️ | Never ⏰ | []
Java |

2.98 KB

|

None

|

0 👍

/

0 👎

package ch.claude_martin.common;
 
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;
 
import ch.claude_martin.common.ToOptional.Ref;
 
/**
 * Collects a single element from a stream into an {@link Optional}. The returned Optional is empty if
 * there is not exactly one element in the stream.
 *
 * <p>
 * This is an alternative to {@link Stream#findAny()} as it checks that there is exactly one element
 * in the stream that can be <i>found</i>. It can also be seen as an alternative to the
 * {@link Collectors}, as this uses an Optional like a {@link Collection}, similar to
 * {@link Collectors#toList()}. 
 * </p>
 *
 * <p>
 * Note that this might take a long time for streams with many elements.
 * </p>
 *
 * <pre>
 * Example:
 * List&lt;Integer> list = Arrays.asList(1,2,3,4);
 * Optional&lt;Integer> o = list.stream().filter(i->i==3).collect(ToOptional.get());
 * System.out.println(o); // Optional[3]
 * o = list.stream().filter(i->i>0).collect(ToOptional.get());
 * System.out.println(o); // Optional.empty
 * </pre>
 * 
 * @see Collectors
 * @param <T>
 *          Type of the expected element.
 */
public final class ToOptional<T> implements Collector<T, Ref<T>, Optional<T>> {
  private ToOptional() {
    super();
  }
 
  public final static ToOptional<?> INSTANCE = new ToOptional<>();
 
  /**
   * Returns an instance of {@link ToOptional}.
   * <p>
   * Note: This always returns the same {@link Collector}.
   */
  @SuppressWarnings("unchecked")
  public static <T> ToOptional<T> get() {
    return (ToOptional<T>) INSTANCE;
  }
 
  static class Ref<RT> {
    private RT value;
    private int count = 0;
 
    public void set(RT value) {
      this.value = value;
      this.count++;
    }
 
    public RT get() {
      return this.value;
    }
 
    public int getCount() {
      return this.count;
    }
  }
 
  @Override
  public Supplier<Ref<T>> supplier() {
    return Ref<T>::new;
  }
 
  @Override
  public BiConsumer<Ref<T>, T> accumulator() {
    return (ref, value) -> {
      ref.set(value);
    };
  }
 
  @Override
  public BinaryOperator<Ref<T>> combiner() {
    return (ref1, ref2) -> {
      if (ref1.getCount() == 0)
        return ref2;
      if (ref2.getCount() == 0)
        return ref1;
      ref1.set(null);// increments count
      return ref1;
    };
  }
 
  @Override
  public Function<Ref<T>, Optional<T>> finisher() {
    return (ref) -> {
      if (ref.getCount() != 1)
        return Optional.empty();
      return Optional.ofNullable(ref.get());
    };
  }
 
  @Override
  public Set<java.util.stream.Collector.Characteristics> characteristics() {
    return Collections.emptySet();
  }
 
}

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎