ProjectAres/Util/core/src/main/java/tc/oc/commons/core/util/Chain.java

144 lines
2.8 KiB
Java

package tc.oc.commons.core.util;
import java.util.AbstractCollection;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Objects;
import javax.annotation.Nullable;
import com.google.common.collect.Iterators;
import tc.oc.commons.core.collection.IterableHelper;
/**
* Append-only linked list
*/
public abstract class Chain<E> extends AbstractCollection<E> implements IterableHelper<E> {
Chain() {}
public Chain<E> push(E e) {
return new Link<>(e, this);
}
public abstract @Nullable E peek();
public abstract E head() throws NoSuchElementException;
public abstract Chain<E> tail() throws NoSuchElementException;
public E getFirst() throws NoSuchElementException {
return head();
}
public Chain<E> removeFirst() throws NoSuchElementException {
return tail();
}
public static <E> Chain<E> empty() {
return Empty.INSTANCE;
}
}
class Empty<E> extends Chain<E> {
static final Empty INSTANCE = new Empty();
private Empty() {}
@Override
public int size() {
return 0;
}
@Override
public boolean isEmpty() {
return true;
}
@Override
public boolean contains(Object o) {
return false;
}
@Override
public @Nullable E peek() {
return null;
}
@Override
public E head() throws NoSuchElementException {
throw new NoSuchElementException();
}
@Override
public Chain<E> tail() throws NoSuchElementException {
throw new NoSuchElementException();
}
@Override
public Iterator<E> iterator() {
return Iterators.emptyIterator();
}
}
class Link<E> extends Chain<E> {
final Chain<E> tail;
final E value;
final int size;
Link(E value, Chain<E> tail) {
this.tail = tail;
this.value = value;
this.size = 1 + tail.size();
}
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public Chain<E> tail() throws NoSuchElementException {
return tail;
}
@Override
public boolean contains(Object o) {
return Objects.equals(value, o) || tail.contains(o);
}
@Override
public E peek() {
return value;
}
@Override
public E head() throws NoSuchElementException {
return value;
}
@Override
public Iterator<E> iterator() {
return new Iterator<E>() {
Chain<E> chain = Link.this;
@Override
public boolean hasNext() {
return !chain.isEmpty();
}
@Override
public E next() {
final E e = chain.head();
chain = chain.tail();
return e;
}
};
}
}