package fr.moresmau.jp.collections; import java.util.AbstractCollection; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import fr.moresmau.jp.func.Function1; import fr.moresmau.jp.func.Mapper; /** * @author JP Moresmau * * @param the class of elements to hold */ public class VList extends AbstractCollection { private int offset; private Block base; private int size=0; /** * construct an empty vlist * @param cls the class of elements to hold */ public VList() { super(); base=new Block(); base.data=new Object[1]; } /** * construct a singleton vlist * @param cls the class of elements to hold */ public VList(T obj) { super(); base=new Block(); base.data=new Object[1]; add(obj); } /** * construct a new vlist on top of another one * @param vl */ protected VList(VList vl){ if (vl.offset>1){ offset=vl.offset-1; base=vl.base; } else { base=vl.base.previousBase; offset=base.lastUsed; } size=vl.size-1; } /** * get the nth element * @param a * @return */ public T get(int a){ if (a<0 || a>=size){ throw new ArrayIndexOutOfBoundsException(a); } if (a==0){ return first(); } int currentOffset=offset; Block currentBase=base; while (a>currentOffset-1){ a-=currentOffset; currentOffset=currentBase.previousOffset; currentBase=currentBase.previousBase; } currentOffset-=a; return (T)currentBase.data[currentOffset-1]; } /** * get the initial element * @return */ public T first(){ if (offset-1 rest(){ if (base.data.length==0 && offset==0){ throw new ArrayIndexOutOfBoundsException(0); } return new VList(this); } /** * add an element at the start * @param val */ public void addFirst(T val){ int newOffset=base.add(val,offset); if (newOffset==-1){ Block newBase=new Block(); newBase.data=new Object[base.data.length*2]; newBase.previousBase=base; newBase.previousOffset=offset; offset=newBase.add(val,0); base=newBase; } else { offset=newOffset; } size++; } @Override public boolean addAll(Collection c) { Object[] o=c.toArray(); for (int a=o.length-1;a>=0;a--){ this.addFirst((T)o[a]); } return true; } public T removeFirst(){ T t=first(); size--; offset--; if (offset<1){ offset=base.previousOffset; if (base.previousBase!=null){ base=base.previousBase; } } return t; } /** * dump to System.out * */ public void dump(){ System.out.println("offset:"+offset); System.out.println(""); base.dump(); } /** * size of list * @return */ public int size(){ return size; } public boolean isEmpty(){ return size==0; } /* (non-Javadoc) * @see java.lang.Iterable#iterator() */ public Iterator iterator(){ return new VListIterator(); } public Iterator reverseIterator(){ return new VListReverseIterator(); } public Iterable reverse(){ return new Iterable(){ public Iterator iterator() { return new VListReverseIterator(); } }; } public VList map(Mapper mapper){ VList ret=new VList(); for (Iterator it=reverseIterator();it.hasNext();){ ret.addFirst(mapper.map(it.next())); } return ret; } public VList filter(Function1 f){ VList ret=new VList(); for (T t:this.reverse()){ if (f.run(t)){ ret.add(t); } } return ret; } /* (non-Javadoc) * @see java.util.Collection#add(java.lang.Object) */ public boolean add(T o) { addFirst(o); return true; } /* (non-Javadoc) * @see java.util.Collection#clear() */ public void clear() { size=0; base=new Block(); base.data=new Object[1]; offset=0; } private class VListIterator implements Iterator{ int count=0; public boolean hasNext() { return VList.this.size()>count; } public T next() { return VList.this.get(count++); } public void remove() { throw new UnsupportedOperationException(); } } private class VListReverseIterator implements Iterator{ int count=VList.this.size()-1; public boolean hasNext() { return count>-1; } public T next() { return VList.this.get(count--); } public void remove() { throw new UnsupportedOperationException(); } } private class Block { Block previousBase; int previousOffset; int lastUsed; Object[] data; int add(T val, int offset){ if (offset==lastUsed && offset