11

Iterable<E> is in java.lang whereas Iterator<E> is in java.util. Is there a good reason for this or is this merely an artifact of bad design?

It seems strange since the only thing that an Iterable<E> is good for is providing an Iterator<E>.

EDIT: One potential reason is because of the (then-)newly introduced for-each loop. I guess my question then would be, are they equivalent?

for(Object o : collection)
    ...
vs
for( Iterator iter = collection.iterator(); iter.hasNext(); ) {
    o = iter.next();
    ...

If they are, then that still doesn't explain why the two classes are in different packages since the compiler would have to import java.util anyways to use the Iterator construct.

tskuzzy
  • 35,812
  • 14
  • 73
  • 140
  • I think if they could do everything from scratch, Iterator would be in java.lang together with Iterable. But as duffymo said, it was in util since 1.2, and you can't really compatibly move a class/interface to another location. – Paŭlo Ebermann Aug 02 '11 at 02:00
  • 1
    @Paulo, they could have, if they wanted to: interface java.lang.Iterator2; interface java.util.Iterator extends java.lang.Iterator2 – Dilum Ranatunga Aug 02 '11 at 02:33
  • 1
    @Paŭlo, actually they wont be in java lang, it'd be just as easy to put another interface w/ the same methods (next/hasNext) in java.lang and java.util.iterator to extend it. Doh, Dilum's comment states the same, my bad not noticing it. – bestsss Aug 03 '11 at 21:54
  • *the compiler would have to import java.util anyways to use the Iterator construct.* the compiler never imports anything, it's the one writing the code. `for (E e: iterable)` does need extra imports which would be the answer of your question. – bestsss Aug 03 '11 at 22:00
  • @bestsss: Actually, not needing the `remove` method in the `for` loop is a good argument for a second Iterator interface. – Paŭlo Ebermann Aug 03 '11 at 22:12

5 Answers5

11

Part of it is history: Iterator has been with us since JDK 1.2, and Iterable came with JDK 1.5. Iterable came in with the enhanced for loop.

Bad design? No, evolution. There's no all-knowing creator. As lessons are learned they're incorporated into the JDK.

Hearen
  • 7,420
  • 4
  • 53
  • 63
duffymo
  • 305,152
  • 44
  • 369
  • 561
  • 3
    What is the "lesson learned" here? Why is `java.lang` a suitable package for something in the Collections API, whose members are by and large in `java.util`? I don't think this answers the question at all. – Mark Peters Aug 02 '11 at 01:50
  • The lesson learned was something along the lines of "oh, crap, guys, we need to model the Iterable concept too". – Karl Knechtel Aug 02 '11 at 02:08
  • Couldn't they have placed `Iterable` in `java.util` though? Although it was released as part of the Collections API, it seems kind of silly to place the two classes into separate packages. – tskuzzy Aug 02 '11 at 02:21
  • Why? I can't answer what the folks who implemented Java were thinking, or tell you what the justifications were. But I can point out that they weren't implemented at the same time. Someone made a strong enough case to put Iterable in java.lang. We'll have to wait for someone who was in on the decision to tell us; the rest is speculation. – duffymo Aug 02 '11 at 09:19
8

java.lang is reserved for classes which are dependencies for language features. Iterable has language level support directly via the for-each loop but Iterator does not.

Mark Peters
  • 80,126
  • 17
  • 159
  • 190
  • Is that an after the fact rationalization? Not really challenging the answer but that doesn't make much sense: java.util.HashMap also has "direct language level support". I always thought that the initial JDK packages had many design errors which were gradually corrected. And thus OP's Q would be answered by 'due to historic legacy reasons'. – alphazero Aug 02 '11 at 01:11
  • 4
    In what way does HashMap have direct language level support? – JimN Aug 02 '11 at 01:13
  • 2
    @alpha: Yeah I'm not really sure where you're coming from on that one. There is syntax which specifically depends on `Iterable`. There is not which depends on `Map`, to my knowledge. At least, not before Java 7. – Mark Peters Aug 02 '11 at 01:48
  • Does the "language level support" for the for-each loop compile down to using an Iterator? That's how I've always thought of it. (see the edit to my question) – tskuzzy Aug 02 '11 at 02:35
  • @tskuzzy: I would assume so, `javap` could help double check. Other answerers are right in that history comes into play...it *might* have made sense to add `Iterator` to `java.lang` as well had it not already existed in `java.util` prior to the for-each loop's introduction. – Mark Peters Aug 02 '11 at 02:49
  • @Mark: I misunderstood your point. I would have understood `Iterable` "/provides/ support for Java at language level e.g. for-each syntactic form". (A good answer.) – alphazero Aug 02 '11 at 03:59
  • This is the correct answer (if indeed there is an answer at all). – Paul Draper Mar 11 '13 at 04:43
  • This reasoning doesn't make, language directly depends on `java.util.Iterator` specifically for for-each syntactic form which uses `Iterator`'s methods `hasNext` and `next` internally. – Konrad Borowski Jul 19 '18 at 12:50
5

Most of the collections implement Iterable so that you can use the convenient for loop syntax:

Iterable<T> someIterableThing;
for (T x : someIterableThing) { ... }

I would imagine that Iterable is in java.lang because it's strongly related to this syntax, a feature of the Java language.

Jeremy Roman
  • 16,137
  • 1
  • 43
  • 44
  • Iterator does not implement Iterable (but every Iterable provides an Iterator via its `iterator()` method. – Paŭlo Ebermann Aug 02 '11 at 01:58
  • Hmm...OK, I'll adjust my answer to remove the problematic text. – Jeremy Roman Aug 02 '11 at 02:06
  • Nice observation! However is the for-each loop equivalent to using an Iterator? (see the edit to my question) – tskuzzy Aug 02 '11 at 02:34
  • @Jeremy, I too suspect this was part of their reasoning, but IMHO it doesn't hold water. After all, in the case where an Iterable is being iterated, an a `java.util` iterator is still eventually necessary. The indirection is just sweeping things under rug. – Dilum Ranatunga Aug 02 '11 at 02:40
  • Well, that part is probably historical since, if I recall correctly `java.util.Iterator` predates both `java.lang.Iterable` and the for-each loop syntax. Had they been created at the same time, I imagine `Iterator` would have ended up in the `java.lang` package. – Jeremy Roman Aug 02 '11 at 02:46
  • @tskuzzy: I believe so, yes (there may be edge cases I am unaware of, but I don't think so). An `Iterable` is defined simply as being something from which you can get an `Iterator` (by calling `iterator()`). And the natural way to iterate over an `Iterator` is what you added to your question. – Jeremy Roman Aug 02 '11 at 02:49
2

Over time, Java's java.* subpackages have developed various circular dependencies. For example,

  1. java.lang.Process -- java.io
  2. java.lang.Readable -- java.io, java.nio
  3. java.lang.String -- java.util
  4. java.lang.System -- java.io, java.nio, java.util

So I think it is best to not think about subpackages as a mechanism to clearly layer dependencies. Rather, the subpackages group related, specialized behavior (except for the catch-all util), and lang selectively pulls in some very useful constructs like Iterator and Locale.

I guess one could also chalk it all up to entropy.

Dilum Ranatunga
  • 13,254
  • 3
  • 41
  • 52
2

To answer the additional question:

The enhanced for loop has two variants. One of them, when the collection argument in

for(E o : collection) {
    ...
}

is something which implements Iterable<E>, is exactly equivalent to

for (Iterator<E> iter = collection.iterator(); iter.hasNext(); ) {
    E o = iter.next();
    ...
}

(with the difference that the Iterator has no variable name that you can access in the rest of the loop). The compiler will generate quite similar or even exactly the same code for each version.

There is another variant of the enhanced for loop: when the collection is an array, it will get compiled to something like this:

E[] a = collection;
for(int i = 0; i < a.length; i++) {
    E o = a[i];
    ...
}

(Of course, here we can't directly access a or i, too.)

By the way, the compiler does not import java.util.Iterator - in the compiled bytecode, each type is referred to by its full name. (And local variables are not really typed, anyway - other for some checkcast assertions.)

Paŭlo Ebermann
  • 73,284
  • 20
  • 146
  • 210