Why doesn't the String class in Java implement Iterable?
There really isn't a good answer. An iterator in Java specifically applies to a collection of discrete items (objects). You would think that a String
, which implements CharSequence
, should be a "collection" of discrete characters. Instead, it is treated as a single entity that happens to consist of characters.
In Java, it seems that iterators are only really applied to collections and not to a string. There is no reason why it is this way (near as I can tell - you would probably have to talk to Gosling or the API writers); it appears to be convention or a design decision. Indeed, there is nothing preventing CharSequence
from implementing Iterable
.
That said, you can iterate over the characters in a string like so:
for (int i = 0; i < str.length(); i++) {
System.out.println(str.charAt(i));
}
Or:
for(char c : str.toCharArray()) {
System.out.println(c);
}
Or:
"Java 8".chars().forEach(System.out::println);
Also note that you cannot modify a character of a String in place because Strings are immutable. The mutable companion to a String is StringBuilder (or the older StringBuffer).
EDIT
To clarify based on the comments on this answer. I'm trying to explain a possible rationale as to why there is no Iterator on a String
. I'm not trying to say that it's not possible; indeed I think it would make sense for CharSequence
to implement Iterable
.
String
provides CharSequence
, which, if only conceptually, is different from a String
. A String
is usually thought of as a single entity, whereas CharSequence
is exactly that: a sequence of characters. It would make sense to have an iterator on a sequence of characters (i.e., on CharSequence
), but not simply on a String
itself.
As Foxfire has rightly pointed out in the comments, String
implements the CharSequence
interface, so type-wise, a String
is a CharSequence
. Semantically, it seems to me that they are two separate things - I'm probably being pedantic here, but when I think of a String
I usually think of it as a single entity that happens to consist of characters. Consider the difference between the sequence of digits 1, 2, 3, 4
and the number 1234
. Now consider the difference between the string abcd
and the sequence of characters a, b, c, d
. I'm trying to point out this difference.
In my opinion, asking why String
doesn't have an iterator is like asking why Integer
doesn't have an iterator so that you can iterate over the individual digits.
The reason is simple: The string class is much older than Iterable.
And obviously nobody ever wanted to add the interface to String (which is somewhat strange because it does implement CharSequence which is based on exactly the same idea).
However it would be somewhat imperformant because Iterable returns an object. So it would have to Wrap every Char returned.
Edit: Just as comparison: .Net does support enumerating on String, however in .Net Iterable also works on native types so there is no wrapping required as it would be required in Java.
For what it's worth, my coworker Josh Bloch strongly wishes to add this feature to Java 7:
for (char c : aString) { ... }
and
for (int codePoint : aString) { ... }
This would be the easiest way to loop over chars and over logical characters (code points) ever. It wouldn't require making String
implement Iterable
, which would force boxing to happen.
Without that language feature, there's not going to be a really good answer to this problem. And he seems very optimistic that he can get this to happen, but I'm not sure.