I am trying to figure out how Guava is creating the iterator that cycles infinitely over itself but I cannot figure it out.
public static <T> Iterable<T> cycle(final Iterable<T> iterable) {
checkNotNull(iterable);
return new FluentIterable<T>() {
#Override
public Iterator<T> iterator() {
return Iterators.cycle(iterable);
}
#Override public String toString() {
return iterable.toString() + " (cycled)";
}
};
}
public static <T> Iterator<T> cycle(final Iterable<T> iterable) {
checkNotNull(iterable);
return new Iterator<T>() {
Iterator<T> iterator = emptyIterator();
Iterator<T> removeFrom;
#Override
public boolean hasNext() {
if (!iterator.hasNext()) {
iterator = iterable.iterator();
}
return iterator.hasNext();
}
#Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
removeFrom = iterator;
return iterator.next();
}
#Override
public void remove() {
checkRemove(removeFrom != null);
removeFrom.remove();
removeFrom = null;
}
};
}
However it does not show how exactly this is achieved. I am missing something probably.
This part of code
if (!iterator.hasNext()) {
iterator = iterable.iterator();
}
checks if old iterator has no more elements. When this is true it simply gets new iterator which will let us start again.
Related
I need to implement my own Iterator for my List class that functions like a Stack and implements java.lang.Iterable.
The Iterator method that is implemented in the List class should return an Iterator.
#Override
public Iterator<E> iterator() {
return new Iterator<>() {
private MyEntry<E> it = begin;
#Override
public boolean hasNext() {
if(pos.next != null) {
return true;
}
else {
return false;
}
}
#Override
public E next() {
if (!hasNext()) {
reset();
}
else {
it = it.next;
}
return it.o;
}
#Override
public void remove() {
}
};
}
The List itself works like a Stack. It has an begin Entry that marks the beginning of the List. Each Entry holds a reference to the next Entry. With the pos Element the List keeps track of its position. The advance() method allows you to pass through the list Entry by Entry. The elem() method returns the Value that the Entry holds at the position pos. The add() method adds an Entry at the end of the List. The delete() method removes the Entry at pos.
import java.util.Iterator;
import java.util.NoSuchElementException;
public class MyList<E> implements Cloneable, java.lang.Iterable {
public MyList() {
pos = begin = new MyEntry<E>();
}
public boolean empty() {
return begin.next == null;
}
public boolean endpos() { // true, if end has been reached
return pos.next == null;
}
public void reset() {
pos = begin;
}
public void advance() {
if (endpos()) {
throw new NoSuchElementException("Already at the end of this List");
}
pos = pos.next;
}
public E elem() {
if (endpos()) {
throw new NoSuchElementException("Already at the end of this List");
}
return pos.next.o;
}
public void add(E x) {
MyEntry<E> newone = new MyEntry<E>(x, pos.next);
pos.next = newone;
}
public void delete() {
if (endpos()) {
throw new NoSuchElementException("Already at the end of this List");
}
pos.next = pos.next.next;
}
The Entrys that the List holds have a Generic Value o and a reference next tho the next MyEntry
class MyEntry<E> {
MyEntry<E> next;
E o;
MyEntry() {
this(null, null);
}
MyEntry(E o) {
this(o, null);
}
MyEntry(E o, MyEntry<E> e) {
this.o = o;
this.next = e;
}
}
But at the moment when I am testing it with my test class MyListTest I get the three test Strings out, but after that the Programm throws an NullPointerException in the next() method at return it.o
import org.junit.Test;
import java.util.*;
public class MyListTest {
#Test
public void test() {
MyList list = new MyList();
Iterator itr = list.iterator();
list.add("a");
list.add("b");
list.add("c");
while(itr.hasNext()) {
Object element = itr.next();
System.out.println(element + " ");
}
iter.remove();
while(itr.hasNext()) {
Object element = itr.next();
System.out.println(element + " ");
}
}
}
My Question is why the Iterator runs out of bounds after the last Entry and how I can prevent that.
So the Solution was that the hasNext() method
#Override
public boolean hasNext() {
if(pos.next != null) {
return true;
}
else {
return false;
}
}
Should have been
#Override
public boolean hasNext() {
if(it.next != null) {
return true;
}
else {
return false;
}
}
Because neither hasNext() nor next() should interfere with the pos element.
The Iterator should keep its own position independent from the rest of the class.
I have generic class MyArray where private member is ArrayList, and inside is implemented iterator.
In Main is given some MyArray with strings and I want to delete all "test" from it... Problem is in iterator which method remove doesn't work
Here is how class looks like:
public class MyArray<E> {
private ArrayList<E> list;
public MyArray() {
list = new ArrayList<E>();
}
public int length() { return list.size(); }
public E at(int pos) { return list.get(pos); }
public void add(E val) { list.add(val); }
public void remove(int pos) { list.remove(pos); }
public class MyIterator implements Iterator<E>{
int index;
#Override
public boolean hasNext() {
return index < list.size();
}
#Override
public E next() {
if (!hasNext())
throw new NoSuchElementException("no next value");
E tmp = list.get(index);
index++;
return tmp;
}
}
public Iterator<E> iterator() {
return new MyIterator();
}
public static void main(String[] args) {
MyArray<String> b = new MyArray<String>();
b.add("This");
b.add("is");
b.add("test");
b.add("please");
b.add("delete");
b.add("all");
b.add("test");
Iterator<String> iter = b.iterator();
while(iter.hasNext())
System.out.println(iter.next());
for(Iterator<String> i = b.iterator(); i.hasNext(); ) {
String tmp = i.next();
if (tmp.equals("test"))
i.remove();
}
Iterator<String> ite = b.iterator();
while(ite.hasNext())
System.out.println(ite.next());
}
}
Exception that I get is:
Exception in thread "main" java.lang.UnsupportedOperationException: remove
at java.util.Iterator.remove(Unknown Source)
at cas1.MyArray.main(MyArray.java:71)
You need to override remove() in your Iterator.
However, it'd be easiest to make your iterator() method return list.iterator(), rather than implementing it yourself:
public Iterator<E> iterator() {
return list.iterator();
}
Iterator in an interface, and you need to implement each of the Iterator methods in MyIterator that you intend to call.
MyIterator that you defined doesn't override Iterator.remove() and
the remove() defined in the Iterator interface is defined as a default method that throws UnsupportedOperationException :
default void remove() {
throw new UnsupportedOperationException("remove");
}
So override it simply to remove effectively the iterated element.
You can rely on ArrayList.Itr code :
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
The list over which I want to iterate, contains an Array.
What I am trying to do is to make it possible to create an Iterator within the Iterator, so that I am able to iterate over the array in every Listelement.
I tried it this way:
#Override
public Iterator<A> iterator() {
return new MyListIterator();
}
private class MyListIterator implements Iterator<A>, Iterable<B>
{
private Listelem current;
private MyListIterator()
{
this.current = head;
}
#Override
public boolean hasNext()
{
return this.current != null;
}
#Override
public A next()
{
A next = this.current.getValue();
this.current = this.current.getSuccessor();
return next;
}
#Override
public void remove()
{
Listelem tmp = head;
while( tmp.getSuccessor().getSuccessor() != this.current )
{
tmp = tmp.getSuccessor();
}
tmp.setSuccessor(this.current);
}
#Override
public Iterator<B> iterator() {
return new MyInnerListIterator();
}
private class MyInnerListIterator implements Iterator<B>
{
private int currentIndex = 0;
private B[] array = current.getAssoc();
#Override
public boolean hasNext() {
return currentIndex < array.length && array[currentIndex] != null;
}
#Override
public B next() {
return array[currentIndex++];
}
#Override
public void remove() {
}
}
}
The problem is, when I am creating the first Iterator with iterator() the object does not contain the method iterator().
Can somebody explain to my why this is not working, and how to do it different?
The problem is that iterator returns an Iterator, even though in this case it happens to also be a MyListIterator. Class Iterator does not have an iterator() function. You need to have iterator() return a MyListIterator, so that you can use methods not in the Iterator interface.
It is likely simpler however, to simply use a for:in loop:
List<Object[]> list = ....
for (Iterator<Object[]> it = list.iterator(); it.hasNext();) {
Object[] arr = it.next();
for (Object o : arr) {
...
}
}
And if you don't need to remove elements from the list, then you can replace the iterator use with another for:in
I have a class Polygon on which I wish to implement two iterators: one to run through all elements (vertices and edges in alternating order) just ONCE, and another to run through them ad infinitum (cyclically).
From a for-each usage standpoint, my guess is that I am only going to be able to have one of the above be the default iterator that can be used with for-each, via implementation of Iterable.iterator(). Is this correct? Or is there a way I could use for-each with both?
Just add two methods returning two different Iterators, one for each case:
public Iterable<String> eachOnce() {
List<String> allResults = new ArrayList<String>();
// fill list
return allResults;
}
public Iterable<String> eachCyclic() {
return new Iterable<String>() {
public Iterator<String> iterator() {
return new Iterator<String>() {
public boolean hasNext() {
return true;
}
public String next() {
// TODO implement
return null;
}
public void remove() {
// do nothing
}
};
}
};
}
This is just an example with a List of Strings, just adapt.
Instead of
for (Polygon p : polygons) { }
just use
for (Polygon p : polygons.eachOnce()) { }
or the cyclic edition
An answer I think is better than those already presented is a method that turns any Iterable into a cyclic one.
public class IterableUtils {
public static class CyclicIterator<T> implements Iterator<T> {
private final Iterable<T> inner;
private Iterator<T> currentIter;
public CyclicIterator(Iterable<T> inner) {
this.inner = inner;
}
public boolean hasNext() {
if (currentIter == null || !currentIter.hasNext()) {
currentIter = inner.iterator();
}
return currentIter.hasNext();
}
public T next() {
if (currentIter == null || !currentIter.hasNext()) {
currentIter = inner.iterator();
}
return currentIter.next();
}
public void remove() {
currentIter.remove();
}
}
public static <T> Iterable<T> cycle(final Iterable<T> i) {
return new Iterable<T>() {
public Iterator<T> iterator() { return new CyclicIterator<T>(i); }
};
}
}
Then you can just implement the single iterator method in the Polygon class and use
for (Element e: polygon) {
...
}
to iterate once and
for (Element e: cycle(polygon)) {
...
}
to iterate endlessly. As a bonus, the cycle modifier can be applied to any iterable.
I am trying to write a class that implements a tree using an array and I need some help to write an Iterator method that which returns an iterator of the elements stored in the tree.
Solution:
public Iterator<E> iterator() {
return new Iterator<E>() {
private int index = 0;
public boolean hasNext() {
return index < ArrayTree.this.size();
}
public E next() {
if (!hasNext()) {
return new NoSuchElementException();
}
return ArrayTree.this.tree[index++];
}
public void remove() {
return new OperationNotSupported();
}
}
}
Without examining your implementation very closely, a very simple implementation might be
public Iterator<E> iterator() {
return new Iterator<E>() {
private int index = 0;
public boolean hasNext() {
return index < ArrayTree.this.size();
}
public E next() {
if (!hasNext()) {
return new NoSuchElementException();
}
return ArrayTree.this.tree[index++];
}
public void remove() {
return new OperationNotSupported();
}
}
}
There are a couple of ways to go, but if your ArrayTree class implements Iterable and Iterator interfaces you'll be on your way.