Re: cloning Iterators?
On 2008-02-18 22:01 +0100, Andreas Leitgeb allegedly wrote:
Owen Jacobson <angrybaldguy@gmail.com> wrote:
To use cloneable you actually need a reference of a type implementing
Cloneable that has a public clone method, rather than of Cloneable.
I'd even be happy, if all the standard collections in java.util had
a method, that took an apt Iterator (i.e. one belonging to that
collection), and returned a new one initially sitting on the same spot.
Appropriate collections could even return a new ListIterator
when given only a plain one.
Without further support for this assertion, I would suspect that if you
end up needing such iterators you're using a wrong data structure. Not
sure, though -- it's just that I can't recall ever having had this need.
At any rate, you could always use a class like this one:
public class CloneableIterator<E>
implements Iterator<E>, Cloneable
{
final Iterator<E>
backing
;
Node<E>
firstHead,
mainHead,
mainTail
;
public CloneableIterator(Iterator<E> it) {
backing = it;
}
public CloneableIterator(Iterable<E> it){
this( it.iterator() );
}
public boolean hasNext() {
if( mainTail == null || mainHead == mainTail ){
return backing.hasNext();
}
else{
return true;
}
}
public void remove() {
throw new UnsupportedOperationException();
}
public E next()
throws NoSuchElementException
{
if( mainTail == null || mainHead == mainTail ){
poll();
}
mainHead = mainHead.next;
return mainHead.object;
}
void poll()
throws NoSuchElementException
{
E o = backing.next(); //throws NSE
Node<E> n = new Node<E>(o);
if( mainTail != null ){
mainTail.next = n;
}
mainTail = n;
if( mainHead == null ){
mainHead = new Node<E>(null);
mainHead.next = mainTail;
firstHead = mainHead;
}
}
public Iterator<E> clone(){
return new ClonedIterator();
}
private static class Node<K> {
final K object;
Node<K> next;
public Node(K o){
object = o;
}
}
private class ClonedIterator
implements Iterator<E>
{
Node<E> myHead = CloneableIterator.this.mainHead;
public void remove() {
throw new UnsupportedOperationException();
}
public E next()
throws NoSuchElementException
{
if( myHead == null ){
if( CloneableIterator.this.firstHead == null ){
CloneableIterator.this.poll(); // throws NSE
}
myHead = CloneableIterator.this.firstHead;
}
if( myHead == CloneableIterator.this.mainTail ){
CloneableIterator.this.poll(); // throws NSE
}
myHead = myHead.next;
return myHead.object;
}
public boolean hasNext() {
if( myHead == null ){
return CloneableIterator.this.firstHead != null ||
CloneableIterator.this.backing.hasNext();
}
else if( myHead != mainTail ){
return true;
}
else{
return CloneableIterator.this.backing.hasNext();
}
}
}
}