Iterator迭代器的使用:
迭代:Iterator,即collection集合元素的通用获取方式java
java.util.Iterator接口。迭代器(对集合进行遍历)数组
有两个经常使用的方法安全
Boolean hasNext()若是仍有元素能够迭代,则返回true
判断集合中还有没有下一个元素,有就返回true,没有就返回false
E next()返回迭代的下一个元素
取出集合中的下一个元素jvm
Iterator迭代器,是一个接口,咱们没法直接使用,须要Iterator接口的实现类对象,获取实现类的方式比较特殊
Collection接口中有一个方法,叫Iterator(),这个方法返回的就是迭代器的实现类对象
Iterator iterator()返回在此collection的元素上进行迭代的迭代器ide
迭代器的使用步骤(重点)
一、使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口接收(多态)
二、使用Iterator接口中的方法hasNext判断还有没有下一个元素
三、使用Iterator接口中的方法next取出集合中的下一个元素优化
package Iterator; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class Demo01Collection { public static void main(String[] args) { //建立一个集合对象 Collection<String> coll=new ArrayList<>(); coll.add("星星"); coll.add("仰望星空"); coll.add("最美的太阳"); coll.add("这就是爱"); //一、使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口接收(多态) //Iterator<E>的接口也是有泛型的,迭代器的泛型跟着集合走,集合是什么泛型,迭代器就是什么泛型 //多态 接口 实现类对象 Iterator<String> it=coll.iterator(); //发现使用迭代器取出集合中元素的代码是一个重复的过程 //因此咱们可使用循环优化 //不知道集合中有多少元素,使用while集合 //循环结束的条件,hasNext方法返回false while (it.hasNext()){ String e=it.next(); System.out.println(e); } // //二、使用Iterator接口中的方法hasNext判断还有没有下一个元素 // boolean b=it.hasNext(); // System.out.println(b);//true // // // 三、使用Iterator接口中的方法next取出集合中的下一个元素 // String s=it.next(); // System.out.println(s); // // //二、使用Iterator接口中的方法hasNext判断还有没有下一个元素 // b=it.hasNext(); // System.out.println(b);//true // // 三、使用Iterator接口中的方法next取出集合中的下一个元素 // s=it.next(); // System.out.println(s); // 二、使用Iterator接口中的方法hasNext判断还有没有下一个元素 // b=it.hasNext(); // System.out.println(b);//true // // 三、使用Iterator接口中的方法next取出集合中的下一个元素 // s=it.next(); // System.out.println(s); // 二、使用Iterator接口中的方法hasNext判断还有没有下一个元素 // b=it.hasNext(); // System.out.println(b);//true // // 三、使用Iterator接口中的方法next取出集合中的下一个元素 // s=it.next(); // System.out.println(s); // // b=it.hasNext(); System.out.println(b);没有元素,返回false // 三、使用Iterator接口中的方法next取出集合中的下一个元素 s=it.next();没有元素,在取出元素会抛出NoSuchElementException没有元素异常 System.out.println(s); } }
Iterator(迭代器)实现原理
这里咱们来看看Java里AbstractList实现Iterator的源代码:this
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> { // List接口实现了Collection<E>, Iterable<E> protected AbstractList() { } public Iterator<E> iterator() { return new Itr(); // 这里返回一个迭代器 } private class Itr implements Iterator<E> { // 内部类Itr实现迭代器 int cursor = 0; int lastRet = -1; int expectedModCount = modCount; public boolean hasNext() { // 实现hasNext方法 return cursor != size(); } public E next() { // 实现next方法 checkForComodification(); try { E next = get(cursor); lastRet = cursor++; return next; } catch (IndexOutOfBoundsException e) { checkForComodification(); throw new NoSuchElementException(); } } public void remove() { // 实现remove方法 if (lastRet == -1) throw new IllegalStateException(); checkForComodification(); try { AbstractList.this.remove(lastRet); if (lastRet < cursor) cursor--; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException e) { throw new ConcurrentModificationException(); } } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } } }
能够看到,实现next()是经过get(cursor),而后cursor++,经过这样实现遍历。code
这部分代码不难看懂,惟一难懂的是remove操做里涉及到的expectedModCount = modCount;对象
在网上查到说这是集合迭代中的一种“快速失败”机制,这种机制提供迭代过程当中集合的安全性。接口
从源代码里能够看到增删操做都会使modCount++,经过和expectedModCount的对比,迭代器能够快速的知道迭代过程当中是否存在list.add()相似的操做,存在的话快速失败!
在第一个例子基础上添加一条语句:
import java.util.*; public class Muster { public static void main(String[] args) { ArrayList list = new ArrayList(); list.add("a"); list.add("b"); list.add("c"); Iterator it = list.iterator(); while(it.hasNext()){ String str = (String) it.next(); System.out.println(str); list.add("s"); //添加一个add方法 } } }
运行结果:
a Exception in thread "main" java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(Unknown Source) at java.util.ArrayList$Itr.next(Unknown Source) at com.hasse.Muster.main(Muster.java:11)
这就会抛出一个下面的异常,迭代终止。
加强for循环
加强for循环的做用: 简化迭代器的书写格式。(注意:加强for循环的底层仍是使用了迭代器遍历。)
加强for循环的适用范围: 若是是实现了Iterable接口的对象或者是数组对象均可以使用加强for循环。
加强for循环的缺点:加强for循环和iterator遍历的效果是同样的,也就说加强for循环的内部也就是调用iteratoer实现的,可是加强for循环有些缺点,例如不能在加强循环里动态的删除集合内容、不能获取下标等。
for(数据类型 变量名 :遍历的目标){ //数据类型 变量名:声明一个变量用来接收遍历目标遍历后的元素 }
int[] arr = {5,11,2,4,9,18}; 普通for循环的遍历方式 for(int i = 0 ; i<arr.length ; i++){ System.out.println("元素:"+ arr[i]); } //使用加强for循环实现 for(int item :arr){ System.out.println("元素:"+ item); }
HashSet<String> set = new HashSet<String>(); //添加元素 set.add("张狗蛋"); set.add("张全蛋"); set.add("张傻蛋"); //使用迭代器遍历Set的集合. Iterator<String> it = set.iterator(); while(it.hasNext()){ String temp = it.next(); System.out.println("元素:"+ temp); it.remove(); } //使用加强for循环解决 for(String item : set){ System.out.println("元素:"+ item); }
注意: Map集合没有实现Iterable接口,因此map集合不能直接使用加强for循环,若是须要使用加强for循环须要借助于Collection的集合。
HashMap<String, String> map = new HashMap<String, String>(); map.put("01","甲"); map.put("02","乙"); map.put("03","丙"); map.put("04","丁"); Set<Map.Entry<String, String>> entrys = map.entrySet(); for(Map.Entry<String, String> entry :entrys){ System.out.println("键:"+ entry.getKey()+" 值:"+ entry.getValue()); }