So what is Iterable in Java? Confused with it and Iterable.
java - What is the difference between iterator and iterable and how to use them? - Stack Overflow
java - Iterable as a return type - Stack Overflow
java - How can I make my class iterable so I can use foreach syntax? - Stack Overflow
Videos
I just had to implement this to iterate through some private data structure. What threw me off is I couldn't index or do checks like I would with an array or list. I understand in general it is exactly like it sounds- used to iterate over some collection. Also that it is something we take for granted such as when using a foreach. That is all I get about it, it just seems like an inconvenience right now...
An Iterable is a simple representation of a series of elements that can be iterated over. It does not have any iteration state such as a "current element". Instead, it has one method that produces an Iterator.
An Iterator is the object with iteration state. It lets you check if it has more elements using hasNext() and move to the next element (if any) using next().
Typically, an Iterable should be able to produce any number of valid Iterators.
An implementation of Iterable is one that provides an Iterator of itself:
public interface Iterable<T>
{
Iterator<T> iterator();
}
An iterator is a simple way of allowing some to loop through a collection of data without assignment privileges (though with ability to remove).
public interface Iterator<E>
{
boolean hasNext();
E next();
void remove();
}
See Javadoc.
It looks like your class should have an implementation of Iterable<ClientInterface> as a class member, like ArrayList.
Let's use this as an example:
public class Bus {
private ArrayList<Person> riders;
... //constructors and other methods
public Iterable<Person> getRiders() {
return riders;
}
... //other methods
}
Everything can be a return type: an enum, a class, an interface, an int, an exception etc.
Iterable is an interface which could be used to use the return in a foreach call (that's why you can use for(T something : AnArrayList) because ArrayList<T> implements Iterable<T>)
Now, my answer contains an example:
We have a method getNeighbours which returns Iterable<ClientInterface>
public Iterable<ClientInterface> getNeighbours()
{
return new Iterable<ClientInterface>();
}
Well, ok since Iterable is just an interface we need to implement methods or use an implementation.
Since it's something which we should do manually we should implement the methods by ourself.
The only method (in Java8, there are 3 methods but we will ignore it) is iterator() which returns an iterator.
public Iterable<ClientInterface> getNeighbours()
{
return new Iterable<ClientInterface>()
{
@Override
public Iterator<ClientInterface> iterator()
{
return null;
}
};
}
Iterator is another interface which is used to provide the logic to iterate over the collection, a list of items etc.
We are forced to implements two methods: hasNext and next
hasNext is used to determinate if there are more items to iterate over, next is used to iterate over it.
public Iterable<ClientInterface> getNeighbours()
{
return new Iterable<ClientInterface>()
{
@Override
public Iterator<ClientInterface> iterator()
{
return new Iterator<ClientInterface>()
{
@Override
public boolean hasNext()
{
return false;
}
@Override
public ClientInterface next()
{
return null;
}
};
}
};
}
We here need to remember which was our last position so we would create a field inside our Iterator.
public Iterable<ClientInterface> getNeighbours()
{
return new Iterable<ClientInterface>()
{
@Override
public Iterator<ClientInterface> iterator()
{
return new Iterator<ClientInterface>()
{
private int position;
@Override
public boolean hasNext()
{
return false;
}
@Override
public ClientInterface next()
{
return null;
}
};
}
};
}
Here the problem: What we should iterate? It depends to you, an example could be:
public Iterable<ClientInterface> getNeighbours()
{
return new Iterable<ClientInterface>()
{
@Override
public Iterator<ClientInterface> iterator()
{
return new Iterator<ClientInterface>()
{
private int position;
private ClientInterface[] items = new ClientInterface[]{new ClientInterface(), new ClientInterface()};
@Override
public boolean hasNext()
{
return position != items.length;
}
@Override
public ClientInterface next()
{
if (!hasNext()) throw new NoSuchElementException();
return items[position++];
}
};
}
};
}
Note here how we created an array of items and used our two methods hasNext and next to provide a way to iterate over it.
Every call of next increment the internal pointer, and our hasNext method just checks if the pointer reached the end of the array.
Collections like ArrayList, LinkedList etc. already did the job for you and better (implements remove method) you can get this iterator by using ArrayList.iterator()
Now you could write something like:
for (ClientInterface el : yourClass.getNeighbours())
{
System.out.println(el);
}
You need to implement the Iterable interface, which means you need to implement the iterator() method. In your case, this might look something like this:
public class BookList implements Iterable<Book> {
private final List<Book> bList = new ArrayList<Book>();
@Override
public Iterator<Book> iterator() {
return bList.iterator();
}
...
}
Implement the Iterable interface. That means you need to implement a method that returns an Iterator object that will iterate over the elements of a BookList.
In this case, your iterator() method could just return the result of calling bList.iterator(). (That will cause for (Book b : somBookList) to iterate over the Book objects in the BookList.bList ... )
In other cases, you might need to write your own Iterator<T> implementation class, complete with T next(), boolean hasNext() and remove() methods. For instance, if you wanted to prevent external code from removing elements from the BookList via your iterator, you might implement it like this:
public class BookList implements Iterable<Book> {
private final List<Book> bList = new ArrayList<Book>();
//...
@Override
public Iterator<Book> iterator() {
return new Iterator<Book> () {
private final Iterator<Book> iter = bList.iterator();
@Override
public boolean hasNext() {
return iter.hasNext();
}
@Override
public Book next() {
return iter.next();
}
@Override
public void remove() {
throw new UnsupportedOperationException("no changes allowed");
}
};
}
}