Since Java 5, we have the new java.lang.Iterable type that can be used in foreach loops as such:
for (Object element : iterable);
The Iterable contract does not specify whether its iterator() method can be called more than once before disposing of the Iterable. I.e., it is not clear whether the following can be expected to work for all Iterables:
for (Object element : iterable);
for (Object element : iterable);
For instance, an Iterator wrapping implementation cannot be used twice:
public class OneShotIterable<T> implements Iterable<T> {
private final Iterator<T> it;
public OneShotIterable(Iterator<T> it) {
this.it = it;
}
@Override
public Iterator<T> iterator() {
return it;
}
}
For most Iterables, this is irrelevant, as they are in fact retro-fitted Collection API types such as List, Set, which already have well-defined contracts for their iterator() methods.
My question is: Is my OneShotIterable implementation violating some contract that I'm overlooking? In other words, will users of an Iterable expect it to be reusable? If so, is there an "official" recommendation by the Java 5 expert group how to deal with such "one shot" Iterables (e.g. throw an IllegalStateException on a second call)?
The Iterable interface has a single abstract method, so it's a functional interface. That means that it can be implemented using a lambda expression or a method reference.
The Collection interface extends Iterable interface, so all subtypes of Collection implement the Iterable interface. This interface stands to represent data-structures whose value can be traversed one by one. This is an important property.
Java Iterator Interface of java collections allows us to access elements of the collection and is used to iterate over the elements in the collection(Map, List or Set). It helps to easily retrieve the elements of a collection and perform operations on each element.
One precedent that I could find in the standard library is the DirectoryStream interface.
Its Javadoc contains the following passage (emphasis theirs):
While
DirectoryStreamextendsIterable, it is not a general-purposeIterableas it supports only a singleIterator; invoking theiteratormethod to obtain a second or subsequent iterator throwsIllegalStateException.
To me, this suggests two things:
Iterable is that you're supposed to be able to iterate more than once (perhaps even concurrently!)IllegalStateException is probably the best way to handle non-compliance in your own classes/interfaces.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With