集合框架遍历方式之——for-each循环
从Java5起,在Java中有了for-each循环,可以用来循环遍历collection和array。Foreach循环允许你在无需保持传统for循环中的索引,或在使用iterator /ListIterator(ArrayList中的一种迭代器实现)时无需调用while循环中的hasNext()方法就能遍历collection。for-each循环简化了任何Collection或array的遍历过程。但是使用foreach循环也有两点需要注意。
- 使用foreach循环的对象,必须实现了Iterable<T>接口
请看如下示例:
import java.util.ArrayList;
public class ForeachTest1 {
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);
}
}
private 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类没有实现Iterable<T>接口,编译期的报错如下:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Can only iterate over an array or an instance of java.lang.Iterable at Text.ForeachTest1.main(ForeachTest1.java:15)
事实上,无需等到编译时才发现报错,eclipse会在这段代码写完之后就会在foreach循环处显示错误:Can only iterate over an array or an instance of java.lang.Iterable
从上述示例可以再次得到确认的是,foreach循环只适用于实现了Iterable<T>接口的对象。由于所有内置Collection类都实现了java.util.Collection接口,已经继承了Iterable,所以为了解决上述问题,可以选择简单地让CustomCollection实现Collection接口或者继承AbstractCollection。解决方式如下:
import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Iterator; public class ForeachTest {
public static void main(String args[]) {
CustomCollection<String> myCollection = new CustomCollection<String>();
myCollection.add("Java");
myCollection.add("Scala");
myCollection.add("Groovy");
for (String language : myCollection) {
System.out.println(language);
}
} private static class CustomCollection<T> extends AbstractCollection<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(Object o) {
return bucket.contains(o);
} public boolean add(T e) {
return bucket.add(e);
} public boolean remove(Object o) {
return bucket.remove(o);
} @Override
public Iterator<T> iterator() {
// TODO Auto-generated method stub
return bucket.iterator();
}
}
}
2.foreach循环的内部实现也是依靠Iterator进行实现的
为了验证foreach循环是使用Iterator作为内部实现这一事实,我们依然采用本文最开始的实例进行验证:
public class ItaratorTest {
public static void main(String[] args) {
Collection<String> list = new ArrayList<String>();
list.add("Android");
list.add("IOS");
list.add("Windows Mobile");
// example1
// Iterator<String> iterator = list.iterator();
// while (iterator.hasNext()) {
// String lang = iterator.next();
// list.remove(lang);
// }
// example 2
for (String language : list) {
list.remove(language);
}
}
}
程序运行时所报异常:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
at java.util.ArrayList$Itr.next(ArrayList.java:831)
at Text.ItaratorTest.main(ItaratorTest.java:22)
此异常正说明了for-each循环内部使用了Iterator来遍历Collection,它也调用了Iterator.next(),这会检查(元素的)变化并抛出ConcurrentModificationException。
总结:
- foreach循环通过iterator实现,使用foreach循环的对象必须实现Iterable接口
集合框架遍历方式之——for-each循环的更多相关文章
- Map集合的遍历方式:
迭代器来遍历 : entrySet() ; keySet(); values(); eg.HashMap<String,String> map = new HashMap<Strin ...
- Map集合的遍历方式以及TreeMap集合保存自定义对象实现比较的Comparable和Comparator两种方式
Map集合的特点 1.Map集合中保存的都是键值对,键和值是一一对应的 2.一个映射不能包含重复的值 3.每个键最多只能映射到一个值上 Map接口和Collection接口的不同 Map是双列集合的根 ...
- List集合的遍历方式
遍历List集合的三种方法 List list = new ArrayList(); list.add("aaa"); list.add("bbb"); lis ...
- day08 集合API | 遍历_ | 泛型 |增强For循环
集合(续) 集合间的操作 集合提供了如取并集,删交集,判断包含子集等操作 package collection; import java.util.ArrayList; import java.uti ...
- set的三种遍历方式-----不能用for循环遍历(无序)
set的三种遍历方式,set遍历元素 list 遍历元素 http://blog.csdn.net/sunrainamazing/article/details/71577662 set遍历元素 ht ...
- Java集合的遍历方式
Map的遍历 1.通过map.entrySet遍历Key和Value Map<Integer,Integer> map = new HashMap<>(); map.put(1 ...
- Java自学-集合框架 遍历
遍历ArrayList的三种方法 步骤 1 : 用for循环遍历 通过前面的学习,知道了可以用size()和get()分别得到大小,和获取指定位置的元素,结合for循环就可以遍历出ArrayList的 ...
- Day11_51_Collections工具类之sort方法和list集合的遍历方式
Collections工具类之sort方法 * 使用Collections工具类对List集合进行排序 Collections.sort(List集合) * Collections.sort()方法只 ...
- Java中List集合的三种遍历方式(全网最详)
List集合在Java日常开发中是必不可少的,只要懂得运用各种各样的方法就可以大大提高我们开发的效率,适当活用各种方法才会使我们开发事半功倍. 我总结了三种List集合的遍历方式,下面一一来介绍. 首 ...
随机推荐
- 二模15day1解题报告
T1.合并序列(minval) 给出长为 n的AB两个序列求两两相加中最小的n个. 据说有证明(在蓝书上,优先队列部分)先把A[1~n]+b[1]入队,然后每取一个a[x]+b[y]就把a[x]+b[ ...
- C#小实例之---C#判断网络
方式一: [DllImport("wininet")] private extern static bool InternetGetConnectedState(out int c ...
- Hibernate单元测试工具junit
相关注解 @Text :测试方法 @Before :初始化方法 @After : 释放资源
- python的optparse模块使用
name or flags:就是参数的名称或标志 -f --file,-q --quit 等,其中-f表示option的缩写,--file表示option的全称 nargs:命令行参数的个数,一般使用 ...
- Processing与Java混编初探
Processing其实是由Java开发出的轻量级JAVA开发语言,主要用于做原型,有setup.draw两个主接口和几个消息相应接口 Processing和Java混编很简单...在Java中引入外 ...
- 【c++】虚基类
何要使用虚基类: 为何避免多层继承中出项多个公共基类所造成的歧义现象 虚基类用法 派生类继承基类时,加上一个virtual关键词则为虚拟基类继承. 在上图程序运行中,我们发现class bass的构造 ...
- Hibernate的查询方式总结
Hibernate的查询方式大体有三种,分别是HQL QBC和SQL三种.在网上查阅一一些资料,做了一个简单的总结. 1. SQL sql 是面向数据库表查询,from 后面跟的是表名,where 后 ...
- redhat yum 从 iso 安装
背景: 1)yum 在没有注册的redhat中无法使用,不能去自动搜索redhat的库 2)使用者不能上网 方法摘自网络,就是下载ISO文件,yum的下载点指向ISO的mount后(也就是解压缩)的目 ...
- UNDO内存结构剖析
UNDO内存结构剖析 一.场景 Oracle的 C事物从早上9:00开始读取A表全部10w行数据,这个而读取需要经历5分钟.在9:01的时候,B事物将A表删除100条记录,那么,当9:05的时候,事物 ...
- MySQL分区表管理
RANGE,LIST分区管理 1:为未分区表创建分区 ALTER TABLE trb3 PARTITION BY KEY(id) PARTITIONS 2; 2:删除某个分区的数据 ALTER TAB ...