144 lines
2.8 KiB
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;
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
|