Skip to content

Instantly share code, notes, and snippets.

@edreyer
Created October 15, 2019 01:07
Show Gist options
  • Save edreyer/4a0524a986227dceb32e88fc4e5679f9 to your computer and use it in GitHub Desktop.
Save edreyer/4a0524a986227dceb32e88fc4e5679f9 to your computer and use it in GitHub Desktop.
Adds some useful operations to Java 8's Optional
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
/**
* Wraps Java's Optional to provide some additional capabilities
*
* Example
* <pre>
* int x = 1;
* int len = Option.
* when(x == 0, () -> "foo").
* when(x == 1, "bar").
* peek(it -> println("value is " + it)).
* filter(it -> it.length() % 2 == 0).
* onEmpty(() -> println("Do this if empty")).
* orElseOp(() -> CGOptional.of("baz")).
* map(String::length).
* orElseThrow(() -> new IllegalStateException());
* // OR orElse(100)
* // OR toOptional()
* // OR ifPresent(a -> ...)
* // etc
* </pre>
*/
public final class Option<T> {
private Optional<T> op;
private Option(Optional<T> op) {
this.op = op;
}
/** */
public static <T> Option<T> of(T value) {
return of(Optional.of(value));
}
/** */
public static <T> Option<T> of(Optional<T> op) {
return new Option(op);
}
/** */
public static <T> Option<T> empty() {
return of(Optional.empty());
}
/** */
public static <T> Option<T> ofNullable(T value) {
return of(Optional.ofNullable(value));
}
/** */
public static <T> Option<T> when(boolean condition, Supplier<? extends T> supplier) {
Objects.requireNonNull(supplier, "supplier is null");
return condition ? of(supplier.get()) : empty();
}
/** */
public static <T> Option<T> when(boolean condition, T value) {
return condition ? of(value) : empty();
}
/**
* null-safe toString. Returns empty String if null
*/
public static <A> String toString(A obj) {
return ofNullable(obj).toString();
}
/** */
public Option<T> orElseOp(T other) {
return op.isPresent() ? this : ofNullable(other);
}
/** */
public Option<T> orElseOp(Option<T> other) {
return op.isPresent() ? this : other;
}
/** */
public Option<T> orElseOp(Supplier<Option<T>> supplier) {
return op.isPresent() ? this : supplier.get();
}
/** */
public Optional<T> toOptional() {
return op;
}
/** nullSafe toString() */
@Override
public String toString() {
return op.map(Object::toString).orElse("");
}
/** */
public boolean isPresent() {
return op.isPresent();
}
/** */
public boolean isEmpty() {
return !op.isPresent();
}
/** */
public void ifPresent(Consumer<? super T> consumer) {
op.ifPresent(consumer);
}
/** */
public Option<T> onEmpty(Runnable action) {
Objects.requireNonNull(action, "action is null");
if (!isPresent()) {
action.run();
}
return this;
}
/** */
public Option<T> peek(Consumer<? super T> action) {
Objects.requireNonNull(action, "action is null");
if (isPresent()) {
action.accept(op.get());
}
return this;
}
/** */
public Option<T> filter(Predicate<? super T> predicate) {
return of(op.filter(predicate));
}
/** */
public <U> Option<U> map(Function<? super T, ? extends U> mapper) {
return of(op.map(mapper));
}
/** */
public <U> Option<U> flatMap(Function<? super T, Optional<U>> mapper) {
return of(op.flatMap(mapper));
}
static <T> Optional<List<T>> sequence(Iterable<? extends Optional<? extends T>> values) {
Objects.requireNonNull(values, "values is null");
List<T> list = new ArrayList<>();
for (Optional<? extends T> value : values) {
if (!value.isPresent()) {
return Optional.empty();
}
list.add(value.get());
}
return Optional.of(list);
}
/** */
public T get() {
return op.get();
}
/** */
public T orElse(T other) {
return op.orElse(other);
}
/** */
public T orElseGet(Supplier<? extends T> other) {
return op.orElseGet(other);
}
/** */
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
return op.orElseThrow(exceptionSupplier);
}
@Override public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Option<?> that = (Option<?>) o;
return Objects.equals(op, that.op);
}
@Override public int hashCode() {
return op != null ? op.hashCode() : 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment