Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any official contract for the Iterable interface with respect to multiple usage?

Tags:

java

iterable

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)?

like image 809
Lukas Eder Avatar asked Apr 03 '13 07:04

Lukas Eder


People also ask

Is iterable a functional interface?

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.

Why do collections extend Iterable?

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.

What is the use of iterator interface?

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.


1 Answers

One precedent that I could find in the standard library is the DirectoryStream interface.

Its Javadoc contains the following passage (emphasis theirs):

While DirectoryStream extends Iterable, it is not a general-purpose Iterable as it supports only a single Iterator; invoking the iterator method to obtain a second or subsequent iterator throws IllegalStateException.

To me, this suggests two things:

  • The implied contract on Iterable is that you're supposed to be able to iterate more than once (perhaps even concurrently!)
  • A boldface warning in the documentation coupled with throwing IllegalStateException is probably the best way to handle non-compliance in your own classes/interfaces.
like image 82
NPE Avatar answered Oct 20 '22 22:10

NPE