企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
## [for-in和迭代器](https://lingcoder.gitee.io/onjava8/#/book/12-Collections?id=for-in%e5%92%8c%e8%bf%ad%e4%bb%a3%e5%99%a8) 到目前为止,*for-in*语法主要用于数组,但它也适用于任何**Collection**对象。实际上在使用**ArrayList**时,已经看到了一些使用它的示例,下面是一个更通用的证明: ~~~ // collections/ForInCollections.java // All collections work with for-in import java.util.*; public class ForInCollections { public static void main(String[] args) { Collection<String> cs = new LinkedList<>(); Collections.addAll(cs, "Take the long way home".split(" ")); for(String s : cs) System.out.print("'" + s + "' "); } } /* Output: 'Take' 'the' 'long' 'way' 'home' */ ~~~ 由于**cs**是一个**Collection**,因此该代码展示了使用*for-in*是所有**Collection**对象的特征。 这样做的原因是 Java 5 引入了一个名为**Iterable**的接口,该接口包含一个能够生成**Iterator**的`iterator()`方法。*for-in*使用此**Iterable**接口来遍历序列。因此,如果创建了任何实现了**Iterable**的类,都可以将它用于*for-in*语句中: ~~~ // collections/IterableClass.java // Anything Iterable works with for-in import java.util.*; public class IterableClass implements Iterable<String> { protected String[] words = ("And that is how " + "we know the Earth to be banana-shaped." ).split(" "); @Override public Iterator<String> iterator() { return new Iterator<String>() { private int index = 0; @Override public boolean hasNext() { return index < words.length; } @Override public String next() { return words[index++]; } @Override public void remove() { // Not implemented throw new UnsupportedOperationException(); } }; } public static void main(String[] args) { for(String s : new IterableClass()) System.out.print(s + " "); } } /* Output: And that is how we know the Earth to be banana-shaped. */ ~~~ `iterator()`返回的是实现了**Iterator**的匿名内部类的实例,该匿名内部类可以遍历数组中的每个单词。在主方法中,可以看到**IterableClass**确实可以用于*for-in*语句。 在 Java 5 中,许多类都是**Iterable**,主要包括所有的**Collection**类(但不包括各种**Maps**)。 例如,下面的代码可以显示所有的操作系统环境变量: ~~~ // collections/EnvironmentVariables.java // {VisuallyInspectOutput} import java.util.*; public class EnvironmentVariables { public static void main(String[] args) { for(Map.Entry entry: System.getenv().entrySet()) { System.out.println(entry.getKey() + ": " + entry.getValue()); } } } ~~~ `System.getenv()`\[^7\]返回一个**Map**,`entrySet()`产生一个由**Map.Entry**的元素构成的**Set**,并且这个**Set**是一个**Iterable**,因此它可以用于*for-in*循环。 *for-in*语句适用于数组或其它任何**Iterable**,但这并不意味着数组肯定也是个**Iterable**,也不会发生任何自动装箱: ~~~ // collections/ArrayIsNotIterable.java import java.util.*; public class ArrayIsNotIterable { static <T> void test(Iterable<T> ib) { for(T t : ib) System.out.print(t + " "); } public static void main(String[] args) { test(Arrays.asList(1, 2, 3)); String[] strings = { "A", "B", "C" }; // An array works in for-in, but it's not Iterable: //- test(strings); // You must explicitly convert it to an Iterable: test(Arrays.asList(strings)); } } /* Output: 1 2 3 A B C */ ~~~ 尝试将数组作为一个**Iterable**参数传递会导致失败。这说明不存在任何从数组到**Iterable**的自动转换; 必须手工执行这种转换。