blob: 325844440936cca7922e1caa8c841713ba051386 [file] [log] [blame]
/*
* Copyright 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package java.util;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import static javaemul.internal.InternalPreconditions.checkCriticalElement;
import static javaemul.internal.InternalPreconditions.checkCriticalNotNull;
import static javaemul.internal.InternalPreconditions.checkNotNull;
/**
* See <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html">
* the official Java API doc</a> for details.
*
* @param <T> type of the wrapped reference
*/
public final class Optional<T> {
@SuppressWarnings("unchecked")
public static <T> Optional<T> empty() {
return (Optional<T>) EMPTY;
}
public static <T> Optional<T> of(T value) {
return new Optional<>(checkCriticalNotNull(value));
}
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
private static final Optional<?> EMPTY = new Optional<>(null);
private final T ref;
private Optional(T ref) {
this.ref = ref;
}
public boolean isPresent() {
return ref != null;
}
public boolean isEmpty() {
return ref == null;
}
public T get() {
checkCriticalElement(isPresent());
return ref;
}
public void ifPresent(Consumer<? super T> consumer) {
if (isPresent()) {
consumer.accept(ref);
}
}
public Optional<T> filter(Predicate<? super T> predicate) {
checkNotNull(predicate);
if (!isPresent() || predicate.test(ref)) {
return this;
}
return empty();
}
public <U> Optional<U> map(Function<? super T, ? extends U> mapper) {
checkNotNull(mapper);
if (isPresent()) {
return ofNullable(mapper.apply(ref));
}
return empty();
}
public <U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
checkNotNull(mapper);
if (isPresent()) {
return checkNotNull(mapper.apply(ref));
}
return empty();
}
public T orElse(T other) {
return isPresent() ? ref : other;
}
public T orElseGet(Supplier<? extends T> other) {
return isPresent() ? ref : other.get();
}
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (isPresent()) {
return ref;
}
throw exceptionSupplier.get();
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof Optional)) {
return false;
}
Optional<?> other = (Optional<?>) obj;
return Objects.equals(ref, other.ref);
}
@Override
public int hashCode() {
return Objects.hashCode(ref);
}
@Override
public String toString() {
return isPresent() ? "Optional.of(" + String.valueOf(ref) + ")" : "Optional.empty()";
}
}