305 lines
8.4 KiB
Java
305 lines
8.4 KiB
Java
package book;
|
|
|
|
import clojure.lang.*;
|
|
import java.util.*;
|
|
|
|
//IPersistentVector, Iterable,
|
|
// List,
|
|
// RandomAccess, Comparable,
|
|
// Serializable, IHashEq
|
|
|
|
public class PersistentSortedList extends Obj implements Iterable, RandomAccess, Comparable,
|
|
IHashEq, IPersistentList, IReduce, ISeq,
|
|
List, Counted{
|
|
final private PersistentTreeMap impl;
|
|
final private int _count;
|
|
static private final PersistentSortedList EMPTY_DEFAULT_COMPARATOR = new PersistentSortedList(null, PersistentTreeMap.EMPTY, 0);
|
|
private int _hasheq = 0;
|
|
|
|
public static PersistentSortedList create(ISeq items){
|
|
PersistentSortedList ret = EMPTY_DEFAULT_COMPARATOR;
|
|
for(; items != null; items = items.next()){
|
|
ret = ret.cons(items.first());
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
public static PersistentSortedList create(Comparator comp, ISeq items){
|
|
PersistentSortedList ret = new PersistentSortedList(null, new PersistentTreeMap(null, comp), 0);
|
|
for(; items != null; items = items.next()){
|
|
ret = ret.cons(items.first());
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
PersistentSortedList(IPersistentMap meta, PersistentTreeMap impl, int count){
|
|
super(meta);
|
|
this.impl = impl;
|
|
this._count = count;
|
|
}
|
|
|
|
@Override
|
|
public int count(){
|
|
return _count;
|
|
}
|
|
|
|
@Override
|
|
public PersistentSortedList cons(final Object o){
|
|
final IPersistentCollection f = (IPersistentCollection) impl.get(o);
|
|
IPersistentCollection newList = f == null ? new PersistentList(o) : f.cons(o);
|
|
return new PersistentSortedList(meta(), impl.assoc(o, newList), _count + 1);
|
|
}
|
|
|
|
@Override
|
|
public IPersistentCollection empty() {
|
|
return new PersistentSortedList(null,
|
|
new PersistentTreeMap(null, this.impl.comp),
|
|
0);
|
|
}
|
|
|
|
@Override
|
|
public boolean equiv(Object obj) {
|
|
if(!(obj instanceof Sequential || obj instanceof List))
|
|
return false;
|
|
ISeq ms = RT.seq(obj);
|
|
for(ISeq s = seq(); s != null; s = s.next(), ms = ms.next()){
|
|
if(ms == null || !Util.equiv(s.first(), ms.first())){
|
|
return false;
|
|
}
|
|
}
|
|
return ms == null;
|
|
}
|
|
|
|
@Override
|
|
public Object peek() {
|
|
if(_count == 0){
|
|
return null;
|
|
}
|
|
final PersistentTreeMap.NodeIterator ite = this.impl.iterator();
|
|
final AMapEntry node = (AMapEntry) ite.next();
|
|
return ((IPersistentCollection) node.val()).seq().first();
|
|
}
|
|
|
|
@Override
|
|
public IPersistentStack pop() {
|
|
if(_count == 0){
|
|
throw new IllegalStateException("Can't pop empty list");
|
|
}
|
|
final PersistentTreeMap.NodeIterator ite = this.impl.iterator();
|
|
final AMapEntry node = (AMapEntry) ite.next();
|
|
if(((IPersistentCollection) node.val()).count() == 1){
|
|
final PersistentTreeMap nextImpl = impl.without(node.getKey());
|
|
return new PersistentSortedList(meta(), nextImpl, _count - 1);
|
|
}
|
|
final PersistentTreeMap nextImpl = impl.assoc(node.getKey(), ((IPersistentStack) node.getValue()).pop());
|
|
return new PersistentSortedList(meta(), nextImpl, _count -1);
|
|
}
|
|
|
|
@Override
|
|
public Object reduce(IFn f) {
|
|
Object ret = first();
|
|
for(ISeq s = (ISeq) next(); s != null; s = s.next()) {
|
|
ret = f.invoke(ret, s.first());
|
|
if (RT.isReduced(ret)) return ((IDeref)ret).deref();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
@Override
|
|
public Object reduce(IFn f, Object start) {
|
|
Object ret = f.invoke(start, first());
|
|
for(PersistentSortedList s = next(); s != null; s = s.next()) {
|
|
if (RT.isReduced(ret)) return ((IDeref)ret).deref();
|
|
ret = f.invoke(ret, s.first());
|
|
}
|
|
if (RT.isReduced(ret)) return ((IDeref)ret).deref();
|
|
return ret;
|
|
}
|
|
|
|
public Object first() {
|
|
return peek();
|
|
}
|
|
|
|
public PersistentSortedList next() {
|
|
if(_count == 0){
|
|
return null;
|
|
}
|
|
final PersistentTreeMap.NodeIterator ite = this.impl.iterator();
|
|
final AMapEntry node = (AMapEntry) ite.next();
|
|
final ISeq nextValue = ((IPersistentCollection) node.val()).seq().next();
|
|
if(nextValue == null){
|
|
final PersistentTreeMap nextImpl = impl.without(node.getKey());
|
|
return impl.count() > 1 ? new PersistentSortedList(meta(), nextImpl, _count - 1) : null;
|
|
}
|
|
final PersistentTreeMap nextImpl = impl.assoc(node.getKey(), nextValue);
|
|
return new PersistentSortedList(meta(), nextImpl, _count - 1);
|
|
}
|
|
|
|
// Things that i did not want to implement.
|
|
|
|
private List reify(){
|
|
return Collections.unmodifiableList(new ArrayList(this));
|
|
}
|
|
|
|
@Override
|
|
public ISeq more() {
|
|
ISeq s = next();
|
|
return s == null ? (PersistentSortedList) empty() : s;
|
|
}
|
|
|
|
@Override
|
|
public Obj withMeta(IPersistentMap meta) {
|
|
if(meta != meta()){
|
|
return new PersistentSortedList(meta, impl, _count);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
@Override
|
|
public int hasheq() {
|
|
if(_hasheq == 0){
|
|
_hasheq = Murmur3.hashOrdered(this);
|
|
}
|
|
return _hasheq;
|
|
}
|
|
|
|
@Override
|
|
public ISeq seq() {
|
|
return count() == 0 ? null : (ISeq) this;
|
|
}
|
|
|
|
@Override
|
|
public int compareTo(Object o) {
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public int size() {
|
|
return count();
|
|
}
|
|
|
|
@Override
|
|
public boolean isEmpty() {
|
|
return seq() == null;
|
|
}
|
|
|
|
@Override
|
|
public boolean contains(Object o) {
|
|
return impl.containsKey(o);
|
|
}
|
|
|
|
@Override
|
|
public Object[] toArray() {
|
|
return RT.seqToArray(seq());
|
|
}
|
|
|
|
@Override
|
|
public boolean add(Object o) {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
|
|
@Override
|
|
public boolean remove(Object o) {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
|
|
@Override
|
|
public boolean addAll(Collection collection) {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
|
|
@Override
|
|
public boolean addAll(int i, Collection collection) {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
|
|
@Override
|
|
public void clear() {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
|
|
@Override
|
|
public Object get(int index) {
|
|
return RT.nth(this, index);
|
|
}
|
|
|
|
@Override
|
|
public Object set(int i, Object o) {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
|
|
@Override
|
|
public void add(int i, Object o) {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
|
|
@Override
|
|
public Object remove(int i) {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
|
|
@Override
|
|
public int indexOf(Object o) {
|
|
// TODO: make this function fast by using the underlying sorted set. This function should be constant.
|
|
ISeq s = seq();
|
|
for(int i = 0; s != null; s = s.next(), i++) {
|
|
if(Util.equiv(s.first(), o)){
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
@Override
|
|
public int lastIndexOf(Object o) {
|
|
// TODO: make this function fast by using the underlying sorted set. This function should be constant.
|
|
return reify().lastIndexOf(o);
|
|
}
|
|
|
|
@Override
|
|
public ListIterator listIterator() {
|
|
return reify().listIterator();
|
|
}
|
|
|
|
@Override
|
|
public ListIterator listIterator(int index) {
|
|
return reify().listIterator(index);
|
|
}
|
|
|
|
@Override
|
|
public List subList(int fromIndex, int toIndex) {
|
|
return reify().subList(fromIndex, toIndex);
|
|
}
|
|
|
|
@Override
|
|
public boolean retainAll(Collection collection) {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
|
|
@Override
|
|
public boolean removeAll(Collection collection) {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
|
|
@Override
|
|
public boolean containsAll(Collection collection) {
|
|
for(Object o : collection) {
|
|
if(!contains(o)){
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public Object[] toArray(Object[] objects) {
|
|
return RT.seqToPassedArray(seq(), objects);
|
|
}
|
|
|
|
@Override
|
|
public Iterator iterator() {
|
|
return new SeqIterator(this);
|
|
}
|
|
}
|
|
|