Enhanced for-loop does not accept Iterator

会有一股神秘感。 提交于 2021-02-05 04:49:28

问题


Excuse me if this has been asked before. My search did not bring up any other similar question. This is something that surprised me in Java.

Apparently, the enhanced for-loop only accepts an array or an instance of java.lang.Iterable. It does not accept a java.util.Iterator as a valid obj reference to iterate over. For example, Eclipse shows an error message for the following code. It says: "Can only iterate over an array or an instance of java.lang.Iterable"

Set<String> mySet = new HashSet<String>();
mySet.add("dummy");
mySet.add("test");
Iterator<String> strings = mySet.iterator();
for (String str : strings) {
    // Process str value ...
}

Why would this be so? I want to know why the enhanced for-loop was designed to work this way. Although an Iterator is not a collection, it can be used to return one element at a time from a collection. Note that the only method in the java.lang.Iterable interface is Iterator<T> iterator() which returns an Iterator. Here, I am directly handing it an Iterator. I know that hasNext() and next() can be used but using the enhanced for-loop makes it look cleaner.

One thing I understand now is that I could use the enhanced for-loop directly over mySet. So I don't even need the extra call to get an Iterator. So, that would be the way to code this, and yes - it does make some sense.


回答1:


The enhanced for loop was part of JSR 201. From that page, you can download the proposed final draft documents, which include a FAQ section directly addressing your question:

Appendix I. Design FAQ

  1. Why can't I use the enhanced for statement with an Iterator (rather than an Iterable or array)?

Two reasons: (1) The construct would not provide much in the way on syntactic improvement if you had an explicit iterator in your code, and (2) Execution of the loop would have the "side effect" of advancing (and typically exhausting) the iterator. In other words, the enhanced for statement provides a simple, elegant, solution for the common case of iterating over a collection or array, and does not attempt to address more complicated cases, which are better addressed with the traditional for statement.

  1. Why can't I use the enhanced for statement to:
    • remove elements as I traverse a collection ("filtering")?
    • simultaneously iterate over multiple collections or arrays?
    • modify the current slot in an array or list?

See Item 1 above. The expert group considered these cases, but opted for a simple, clean extension that dose(sic) one thing well. The design obeys the "80-20 rule" (it handles 80% of the cases with 20% of the effort). If a case falls into the other 20%, you can always use an explicit iterator or index as you've done in the past.

In other words, the committee chose to limit the scope of the proposal, and some features that one could imagine being part of the proposal didn't make the cut.




回答2:


The enhanced for loop was introduced in Java 5 as a simpler way to iterate through all the elements of a Collection [or an array].

http://www.cis.upenn.edu/~matuszek/General/JavaSyntax/enhanced-for-loops.html

An iterator is not a collection of elements,

it is an object that enables a programmer to traverse a container. An iterator may be thought of as a type of pointer.

https://en.wikipedia.org/wiki/Iterator

So enhanced for loops work by going through all the elements in a structure that contains elements, while an iterator doesn't contain elements, it acts more like a pointer.




回答3:


In your example, you are creating an iterator but not using it properly. As to answer your question of why the exception is being thrown- it's from the line:

 for (String str : strings) {

"strings" is an iterator here, not a collection that you can iterate through. So you have a few options you can iterate through the set by using an enhanced for loop:

for(String myString : mySet){
    //do work
}

or you can iterate through the set using an iterator:

Iterator<String> strings = mySet.iterator();
while(strings.hasNext()){
    //do work
}

hope you find this helpful.




回答4:


The error comes because you are trying to iterate over an Iterator, and not a List or Collection. If you want to use the Iterator, i recommend you to use it next() and hasNext() methods:

Set<String> mySet = new HashSet<String>();
mySet.add("dummy");
mySet.add("test");
Iterator<String> strings = mySet.iterator();
while(strings.hasNext()){
    String temp = strings.next();
    System.out.println(temp);
}


来源:https://stackoverflow.com/questions/31348033/enhanced-for-loop-does-not-accept-iterator

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!