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
DirectoryStream
extendsIterable
, it is not a general-purposeIterable
as it supports only a singleIterator
; invoking theiterator
method 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