从Java5起,在Java中有了for-each循环,可以用来循环遍历collection和array。For each循环允许你在无需保持传统for循环中的索引,或在使用iterator /ListIterator时无需调用while循环中的hasNext()方法就能遍历collection。Java中,for-each循环简化了任何Collection或array的遍历过程,但并不是每个Java程序员都了解本文将要描述的for-each 循环的一些细节。与 Java5 发布的其他术语:释放别名泛型,自动封装和可变参数不同,Java开发者对for-each循环的使用比任何其他特性更加频繁,但当问及高级的for-each循环怎样工作,或什么是在for-each循环中使用Collection时的基本需求时,就不是每个人都能够回答的了。本篇教程和例子旨在通过深入研究for-each 循环中几个有趣的难题来填补上述空白(说明上述问题)。好了,不再赘述,一起看看我们在Java5 for-each循环的第一个问题。
高级循环问题 1
考虑下面这段遍历一个用户自定义的aggregator或collection类的代码,这段代码将会打印出什么,抛出异常还是编译器错误:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
package test;
/** * Java Class to show how for-each loop works in Java
*/
public class ForEachTest {
public static void main(String args[]){
CustomCollection<String> myCollection = new CustomCollection<String>();
myCollection.add( "Java" );
myCollection.add( "Scala" );
myCollection.add( "Groovy" );
//What does this code will do, print language, throw exception or compile time error
for (String language: myCollection){
System.out.println(language);
}
}
} |
下面是我们的CustomCollection类,这是个参数为泛型的类,与任何其他的Collection类相似,依靠于ArrayList并提供从Collection中添加和删除项的方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
package test;
public class CustomCollection<T>{
private ArrayList<T> bucket;
public CustomCollection(){
bucket = new ArrayList();
}
public int size() {
return bucket.size();
}
public boolean isEmpty() {
return bucket.isEmpty();
}
public boolean contains(T o) {
return bucket.contains(o);
}
public boolean add(T e) {
return bucket.add(e);
}
public boolean remove(T o) {
return bucket.remove(o);
}
} |
答案:
上述代码将无法通过编译,这是因为我们的CustomCollection类没有实现java.lang.Iterable接口,编译期错误如下:
1
2
3
4
5
|
Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - for -each not applicable to expression type
required: array or java.lang.Iterable
found: test .CustomCollection
at test .ForEachTest.main(ForEachTest.java:24)
|
从中了解到的一个有趣的事实是:for-each循环仅应用于实现了Iterable接口的Java array和Collection类,而且既然所有内置Collection类都实现了java.util.Collection接口,已经继承了Iterable,这一细节通常会被忽略,这点可以在Collection接口的类型声明“ public interface Collection extends Iterable”中看到。所以为了解决上述问题,你可以选择简单地让CustomCollection实现Collection接口或者继承AbstractCollection,这是默认的通用实现并展示了如何同时使用抽象类和接口以获取更好的灵活性。现在让我们来看看for-each循环的第二个难题:
Java for-each循环的第二个难题:
在下面的代码示例将会抛出ConcurrentModificationException异常。这里我们使用标准iterator和for-each循环遍历ArrayList,随后删除元素,你需要找出哪段代码将会抛出ConcurrentModificationException ,为什么?请注意,答案可能是两个都会,都不会或其中之一。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
package test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/** * Java class to demonstrate inner working of for-each loop in Java
* @author Javin Paul
**/
public class ForEachTest2 {
public static void main(String args[]){
Collection<String> list = new ArrayList<String>();
list.add( "Android" );
list.add( "iPhone" );
list.add( "Windows Mobile" );
// Which Code will throw ConcurrentModificationException, both,
// none or one of them
// example 1
Iterator<String> itr = list.iterator();
while (itr.hasNext()){
String lang = itr.next();
list.remove(lang);
}
// example 2
for (String language: list){
list.remove(language);
}
}
} |
大约70%的Java开发者都会说第一个代码块会抛出ConcurrentModificationException异常,因为我们没有用iterator的remove方法来删除元素,而是使用ArrayList的 remove()方法。但是,没有多少Java开发者会说出for-each循环也会出现同样的问题,因为我们在这里没有使用iterator。事实上,第二个代码片段也会抛出ConcurrentModificationException异常,这点在解决了第一个困惑之后就变得很明显了。既然for-each循环内部使用了Iterator来遍历Collection,它也调用了Iterator.next(),这会检查(元素的)变化并抛出ConcurrentModificationException。你可以从下面的输出中了解到这点,在注释掉第一个代码段后,当你运行第二个代码段时会得到下面的输出。
1
2
3
4
|
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at test .ForEachTest2.main(ForEachTest2.java:34)
|
以上就是关于Java5 for-each循环的全部内容。我们已经看到了Java程序员在编写遍历Collection类的代码时产生的很多问题,特别是在遍历collection的同时删除元素的时候。请牢记,在从任何Collection(例如Map、Set或List)中删除对象时总要使用Iterator的remove方法,也请谨记for-each循环只是标准Iterator代码标准用法之上的一种语法糖(syntactic sugar)而已。
译者注:语法糖(syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达-Peter J. Landin发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会。
REFS:http://www.importnew.com/11038.html
相关推荐
Java的for-each循环,也称为增强for循环,是自Java 5引入的一项特性,它极大地简化了集合和数组的遍历操作。在传统的for循环中,我们需要手动管理索引,而在迭代器模式中,我们需要调用`hasNext()`和`next()`方法。...
在Java编程语言中,`for-each`循环和迭代器是两种主要的遍历集合(如数组和集合)的方式。本文将深入探讨这两种方法,并强调它们的用途、优点以及潜在的陷阱。 首先,我们来看一下迭代器(Iterator)。迭代器是Java...
下面是用一个传统的for循环遍历集合的例子:用传统的for循环遍历数组的做法如下:这些做法逗比while循环更好,但是它们并不完美。如果真的那么不幸,并且外部集
For-Each循环(也称为增强For循环)是Java 5引入的新特性,主要用于遍历集合或数组中的每个元素。其语法为: ```java for (类型 变量 : 集合/数组) { // 循环体 } ``` 假设`Demo4.java`演示了使用For-Each...
Java 5引入了一种更简洁的循环方式,称为`for-each`循环,特别适用于遍历集合和数组。例如,遍历一个ArrayList: ```java List<String> list = new ArrayList(); list.add("Apple"); list.add("Banana"); list.add...
5. 并行for-each循环(Java 8+): 自Java 8起,可以使用`Parallel Streams`进行并行遍历,提高性能。例如: ```java IntStream.rangeClosed(1, 10).parallel().forEach(System.out::println); ``` 这将并行...
2. 遍历数组或集合:for-each循环(增强for循环)使得遍历数组或集合更加简洁。 ```java int[] numbers = {1, 2, 3, 4, 5}; for (int num : numbers) { System.out.println(num); } ``` 这里会依次打印出数组中的每...
除了基本形式,Java还支持更复杂的For循环结构,如For-Each循环(也称为增强For循环),它简化了遍历数组或集合的操作。For-Each循环的语法如下: ```java for (数据类型 变量 : 集合或数组) { // 循环体 } ``` ...
Java 5引入了一种更简洁的循环方式,被称为for-each循环或增强型for循环,它主要用于遍历数组或集合。基本语法如下: ```java for (类型 变量 : 集合或数组) { // 循环体代码 } ``` 例如,遍历一个整数数组: ```...
在Java中,可以使用循环结构,如for-each循环或传统for循环,遍历数组并打印元素。以下是一个示例: ```java public class ArrayOutput { public static void main(String[] args) { int[] numbers = {1, 2, 3, 4...
Java for循环类For循环上的Java分配使用“ for”循环计数到100给定一个主要功能: int lastNumber = 100 ;System . out . println( " Starting Count to " + lastNumber);countTheNumbers(lastNumber); 创建一个...
在Java编程语言中,"斗地主发牌"是一个典型的示例,用于教授和实践基本的面向对象编程概念,如构造函数、对象数组以及for-each循环。斗地主是一种广受欢迎的扑克游戏,通常涉及三名玩家和一副54张牌的牌组。在这个...
遍历ArrayList通常使用for-each循环,这是一种简洁且高效的迭代方式: ```java ArrayList<String> list = new ArrayList(); list.add("A"); list.add("B"); list.add("C"); for (String item : list) { System....
- For-Each循环,又称为增强型for循环,是从Java 5开始引入的。它的主要目的是简化对数组和集合的遍历。在传统的for循环中,我们需要手动初始化、递增和检查终止条件。而For-Each循环通过以下语法糖简化了这一过程...
Java for循环类For循环上的Java分配使用“ for”循环计数到100给定一个主要功能: int lastNumber = 100 ;System . out . println( " Starting Count to " + lastNumber);countTheNumbers(lastNumber); 创建一个...
3. **控制结构**:VB的`If...Then...Else`在Java中是`if (condition) {...} else {...}`,`For Each`循环转换为Java的`for-each`循环,`Do...Loop`可以映射为Java的`while`或`do-while`循环。 4. **事件处理**:VB...
#### 二、增强型For循环(For-Each循环) 增强型For循环是Java 5引入的一种新的循环机制,用于简化对数组或集合的操作。例如: ```java String[] arr = new String[]{"a", "b", "c"}; for (String s : arr) { ...
- 遍历数组:可以使用for-each循环遍历JSON数组的所有元素。 - 添加/删除元素:同样,某些库提供添加或删除数组元素的方法。 5. JSONPath和JSONSchema: JSONPath是类似于XPath的JSON查询语言,用于从JSON文档中...
总的来说,Java的for-each循环提供了更直观、更安全的方式来遍历数组和集合,减少了代码量,提高了可读性,并降低了潜在的编程错误。这是一个非常实用的特性,自JDK 5以来就被广泛使用,并且在后续的JDK版本中得到了...