Why aren't Enumerations Iterable? - java

In Java 5 and above you have the foreach loop, which works magically on anything that implements Iterable:
for (Object o : list) {
doStuff(o);
}
However, Enumerable still does not implement Iterable, meaning that to iterate over an Enumeration you must do the following:
for(; e.hasMoreElements() ;) {
doStuff(e.nextElement());
}
Does anyone know if there is a reason why Enumeration still does not implement Iterable?
Edit: As a clarification, I'm not talking about the language concept of an enum, I'm talking a Java-specific class in the Java API called 'Enumeration'.

As an easy and clean way of using an Enumeration with the enhanced for loop, convert to an ArrayList with java.util.Collections.list.
for (TableColumn col : Collections.list(columnModel.getColumns()) {
(javax.swing.table.TableColumnModel.getColumns returns Enumeration.)
Note, this may be very slightly less efficient.

It doesn't make sense for Enumeration to implement Iterable. Iterable is a factory method for Iterator. Enumeration is analogous to Iterator, and only maintains state for a single enumeration.
So, be careful trying to wrap an Enumeration as an Iterable. If someone passes me an Iterable, I will assume that I can call iterator() on it repeatedly, creating as many Iterator instances as I want, and iterating independently on each. A wrapped Enumeration will not fulfill this contract; don't let your wrapped Enumeration escape from your own code. (As an aside, I noticed that Java 7's DirectoryStream violates expectations in just this way, and shouldn't be allowed to "escape" either.)
Enumeration is like an Iterator, not an Iterable. A Collection is Iterable. An Iterator is not.
You can't do this:
Vector<X> list = …
Iterator<X> i = list.iterator();
for (X x : i) {
x.doStuff();
}
So it wouldn't make sense to do this:
Vector<X> list = …
Enumeration<X> i = list.enumeration();
for (X x : i) {
x.doStuff();
}
There is no Enumerable equivalent to Iterable. It could be added without breaking anything to work in for loops, but what would be the point? If you are able to implement this new Enumerable interface, why not just implement Iterable instead?

Enumeration hasn't been modified to support Iterable because it's an interface not a concrete class (like Vector, which was modifed to support the Collections interface).
If Enumeration was changed to support Iterable it would break a bunch of people's code.

AFAIK Enumeration is kinda "deprecated":
Iterator takes the place of
Enumeration in the Java collections
framework
I hope they'll change the Servlet API with JSR 315 to use Iterator instead of Enumeration.

If you would just like it to be syntactically a little cleaner, you can use:
while(e.hasMoreElements()) {
doStuff(e.nextElement());
}

It is possible to create an Iterable from any object with a method that returns an Enumeration, using a lambda as an adapter. In Java 8, use Guava's static Iterators.forEnumeration method, and in Java 9+ use the Enumeration instance method asIterator.
Consider the Servlet API's HttpSession.getAttributeNames(), which returns an Enumeration<String> rather than an Iterator<String>.
Java 8 using Guava
Iterable<String> iterable = () -> Iterators.forEnumeration(session.getAttributeNames());
Java 9+
Iterable<String> iterable = () -> session.getAttributeNames().asIterator();
Note that these lambdas are truly Iterable; they return a fresh Iterator each time they are invoked. You can use them exactly like any other Iterable in an enhanced for loop, StreamSupport.stream(iterable.spliterator(), false), and iterable.forEach().
The same trick works on classes that provide an Iterator but don't implement Iterable. Iterable<Something> iterable = notIterable::createIterator;

Related

Java iterator<Object> content access

First, I must say that I learned Java at school (the basics...) and C++ at university (OOP). Soon I will write a Java project, and now I'm looking for the equivalent of STL in Java.
I'm learning to use iterators in Java, I've been looking for a way to access the content of the iterator without using the methods next(), previous() (which I've seen here).
I mean the cast: iterator to Object, like operator * in pointers.
The code compiles when I write (Object)obj But I get Java.lang.ClassCastException.
The Java equivalent to STL containers are the Collection, List, Set, and Map interfaces. The most common concrete implementations of those interfaces are ArrayList, HashSet, TreeSet, HashMap, and TreeMap.
Iterators are an old, uncommonly-used interface in Java. You normally will not need to work with iterators. Instead, use enhanced for loop syntax to loop over a container directly:
List<String> names = new ArrayList<>();
for (String name: names) {
System.out.printf("Hello %s%n!", name);
}
If you do use iterators, calling next() is the way to access the container's elements. Each call returns the next element in the collection. There is no other way. An iterator is not a pointer; you can't access its contents by dereferencing it or casting it or anything like that. You call next().

why does the Collections utility class does not have a Iterator method in Java?

The Collections utility class has static methods that operate on collection. For example,
Collections.Sort(list) that sorts the list.
why not a method of type
static <T> Iterator<T> iterator() { }
In this way, I could get an iterator over my collection as
Iterator it = Colletions.iterator(list)
The Collections do have emptyIterator() and emptyListIterator(), but I dont understand what purpose do they serve?
There's no need for a Collections.iterator(Collection) method, because the Collection interface has an iterator() method that returns an Iterator already. It only makes sense when you have a Collection already, and the Iterator is coupled with the Collection anyway. What would Collections.iterator(Collection c) do? It would probably just call return c.iterator();.
I suppose that Collections.emptyIterator() and Collections.emptyListIterator() save the caller the processing to create an empty Collection / List just to call its iterator() / listIterator() method.
The GRASP pattern "Information Expert" would indicate that the design of an Iterator would be with the class it iterates, because the class itself has the information needed to create an Iterator.
It doesn't need an iterator method because it's already defined in the Collection Interface. It needs be so, because for different Collection classes the iterators can't work the same (internally) even if they provide the same functionality (externally).
[EDIT. Thanks, Marko.] Empty iterators allow you to write cleaner code, eliminating the need to cover special edge cases, and there's only one way to provide an empty iterator. Thus, it's defined in the Collections class with its predefined behavior.
But we have Collection.iterator(), that's exactly what you're looking for.
The Collections class contains a bunch of utility methods that are generic for all kinds of collections, whereas all the collections that implement the Collection interface contain specific implementations of a given functionality.
Because each Collection already has its own iterator, it doesn't make sense to have it as an utility method in Collections, besides it would be trivial to implement: just return the result of calling the iterator() method on the Collection received as parameter.
I'll answer only the "purpose of the empty iterator" part.
Consider this method:
boolean containsEvil(String x) {
return x.contains("evil");
}
This method will fail for a null-argument, which is an edge case for it and it would need special handling to avoid the failure. However, if you take care in the rest of your program to never use null arguments and represent the concept of "no string" as an empty string, you don't need to handle the special case.
Occasionally you may also have an Iterator-based API:
boolean containsEvil(Iterator<String> xs) {
while (xs.hasNext()) if (containsEvil(xs.next()) return true;
return false;
}
Again, this will fail for a null-argument, so you will want to have an empty iterator factory around to stand for the "no iterator" case. In broader terms, you want your zero element in the iterator space, just as you want it in the string space.

Why cant I use an Iterator this way?

Iterator<String> iterator=...
//right way
for (Iterator<String> i = iterator; i.hasNext(); ){
System.out.println(i.next());
}
//why can't?
for(String i:iterator){
}
Reference:
http://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html
http://docs.oracle.com/javase/6/docs/api/java/util/Iterator.html
You can do more compactly:
for(String i:list){
}
The syntax is only for Iterables (and arrays), not for their Iterators directly (and also not for Enumerations).
Why not? I don't know... Maybe too much complexity/effort (in the compiler implementation) for a "rare" case. Or edge-cases that would cause trouble (such as an Iterable that is also an Iterator, I think some people make such beasts).
Maybe try libraries like Google Guava to get some more convenient ways to work with Iterators, Collections, and friends.
The compiler checks the syntax for the for enhanced and requires that the expression after the colon returns an object that implements the Iterable interface. Iterator doesn't implement it.
You can only use the for loop syntax with objects that implement the Iterable interface.
Iterators are not iterable.
for(String i:list){
//
}

Java: why can't iterate over an iterator?

I read Why is Java's Iterator not an Iterable? and Why aren't Enumerations Iterable?, but I still don't understand why this:
void foo(Iterator<X> it) {
for (X x : it) {
bar(x);
baz(x);
}
}
was not made possible. In other words, unless I'm missing something, the above could have been nice and valid syntactic sugar for:
void foo(Iterator<X> it) {
for (X x; it.hasNext();) {
x = it.next();
bar(x);
baz(x);
}
}
Most likely the reason for this is because iterators are not reusable; you need to get a fresh Iterator from the Iterable collection each time you want to iterate over the elements. However, as a quick fix:
private static <T> Iterable<T> iterable(final Iterator<T> it){
return new Iterable<T>(){ public Iterator<T> iterator(){ return it; } };
}
//....
{
// ...
// Now we can use:
for ( X x : iterable(it) ){
// do something with x
}
// ...
}
//....
That said, the best thing to do is simply pass around the Iterable<T> interface instead of Iterator<T>
but I still don't understand why this [...] was not made possible.
I can see several reasons:
Iterators are not reusable, so a for/each would consume the iterator - not incorrect behavior, perhaps, but unintuitive to those who don't know how the for/each is desugared.
Iterators don't appear "naked" in code all that often so it would be complicating the JLS with little gain (the for/each construct is bad enough as it is, working on both Iterables and arrays).
There's an easy workaround. It may seem a little wasteful to allocate a new object just for this, but allocation is cheap as it is and escape analysis would rid you even of that small cost in most cases. (Why they didn't include this workaround in an Iterables utility class, analogous to Collections and Arrays, is beyond me, though.)
(Probably not true - see the comments.) I seem to recall that the JLS can only reference things in java.lang[citation needed], so they'd have to create an Iterator interface in java.lang which java.util.Iterator extends without adding anything to. Now we have two functionally equivalent iterator interfaces. 50% of the new code using naked iterators will choose the java.lang version, the rest use the one in java.util. Chaos ensues, compatibility problems abound, etc.
I think points 1-3 are very much in line with how the Java language design philosophy seems to go: Don't surprise newcomers, don't complicate the spec if it doesn't have a clear gain that overshadows the costs, and don't do with a language feature what can be done with a library.
The same arguments would explain why java.util.Enumeration isn't Iterable, too.
The for(Type t : iterable) syntax is only valid for classes that implement Iterable<Type>.
An iterator does not implement iterable.
You can iterate over things like Collection<T>, List<T>, or Set<T> because they implement Iterable.
The following code is equivalent:
for (Type t: list) {
// do something with t
}
and
Iterator<Type> iter = list.iterator();
while (iter.hasNext()) {
t = iter.next();
// do something with t
}
The reason this was not made possible, is because the for-each syntax was added to the language to abstract out the Iterator. Making the for-each loop work with iterators would not accomplish what the for-each loop was created for.
Actually, you can.
There is very short workaround available on java 8:
for (X item : (Iterable<X>) () -> iterator)
See How to iterate with foreach loop over java 8 stream for the detailed explanation of the trick.
And some explanations why this was not natively supported can be found in related question:
Why does Stream<T> not implement Iterable<T>?
Iterators are not meant be reused (i.e.: used in more than one iteration loop). In particular, Iterator.hasNext() guarantees that you can safely call Iterator.next() and indeed get the next value from the underlying collection.
When the same iterator is used in two concurrently running iterations (let's assume a multi-threading scenario), this promise can no longer be kept:
while(iter.hasNext() {
// Now a context switch happens, another thread is performing
// iter.hasNext(); x = iter.next();
String s = iter.next();
// A runtime exception is thrown because the iterator was
// exhausted by the other thread
}
Such scenarios completely break the protocol offered by Iterator. Actually, they can occur even in a single threaded program: an iteration loop calls another method which uses the same iterator to perform its own iteration. When this method returns, the caller is issuing an Iterator.next() call which, again, fails.
Because the for-each is designed to read as something like:
for each element of [some collection of elements]
An Iterator is not [some collection of elements]. An array and an Iterable is.

What is the Iterable interface used for?

I am a beginner and I cannot understand the real effect of the Iterable interface.
Besides what Jeremy said, its main benefit is that it has its own bit of syntactic sugar: the enhanced for-loop. If you have, say, an Iterable<String>, you can do:
for (String str : myIterable) {
...
}
Nice and easy, isn't it? All the dirty work of creating the Iterator<String>, checking if it hasNext(), and calling str = getNext() is handled behind the scenes by the compiler.
And since most collections either implement Iterable or have a view that returns one (such as Map's keySet() or values()), this makes working with collections much easier.
The Iterable Javadoc gives a full list of classes that implement Iterable.
If you have a complicated data set, like a tree or a helical queue (yes, I just made that up), but you don't care how it's structured internally, you just want to get all elements one by one, you get it to return an iterator.
The complex object in question, be it a tree or a queue or a WombleBasket implements Iterable, and can return an iterator object that you can query using the Iterator methods.
That way, you can just ask it if it hasNext(), and if it does, you get the next() item, without worrying where to get it from the tree or wherever.
It returns an java.util.Iterator. It is mainly used to be able to use the implementing type in the enhanced for loop
List<Item> list = ...
for (Item i:list) {
// use i
}
Under the hood the compiler calls the list.iterator() and iterates it giving you the i inside the for loop.
An interface is at its heart a list of methods that a class should implement. The iterable interface is very simple -- there is only one method to implement: Iterator(). When a class implements the Iterable interface, it is telling other classes that you can get an Iterator object to use to iterate over (i.e., traverse) the data in the object.
Iterators basically allow for iteration over any Collection.
It's also what is required to use Java's for-each control statement.
The Iterable is defined as a generic type.
Iterable , where T type parameter represents the type of elements returned by the iterator.
An object that implements this interface allows it to be the target of the “foreach” statement. The for-each loop is used for iterating over arrays, collections.
read more -: https://examples.javacodegeeks.com/iterable-java-example-java-lang-iterable-interface/

Categories