1.1. 迭代器
为了方便的处理集合中的元素,Java中出现了一个对象,该对象提供了一些方法专门处理集合中的元素.例如删除和获取集合中的元素.该对象就叫做迭代器(Iterator).
对 Collection 进行迭代的类,称其为迭代器。还是面向对象的思想,专业对象做专业的事情,迭代器就是专门取出集合元素的对象。但是该对象比较特殊,不能直接创建对象(通过new),该对象是以内部类的形式存在于每个集合类的内部。
如何获取迭代器?Collection接口中定义了获取集合类迭代器的方法(iterator()),所以所有的Collection体系集合都可以获取自身的迭代器。
正是由于每一个容器都有取出元素的功能。这些功能定义都一样,只不过实现的具体方式不同(因为每一个容器的数据结构不一样)所以对共性的取出功能进行了抽取,从而出现了Iterator接口。而每一个容器都在其内部对该接口进行了内部类的实现。也就是将取出方式的细节进行封装。
1.1.1. Iterable
Jdk1.5之后添加的新接口, Collection的父接口. 实现了Iterable的类就是可迭代的.并且支持增强for循环。该接口只有一个方法即获取迭代器的方法iterator()可以获取每个容器自身的迭代器Iterator。(Collection)集合容器都需要获取迭代器(Iterator)于是在5.0后又进行了抽取将获取容器迭代器的iterator()方法放入到了Iterable接口中。Collection接口进程了Iterable,所以Collection体系都具备获取自身迭代器的方法,只不过每个子类集合都进行了重写(因为数据结构不同)
1.1.2. Iterator
Iterator iterator() 返回该集合的迭代器对象
该类主要用于遍历集合对象,该类描述了遍历集合的常见方法 1:java.lang. Itreable ---| Itreable 接口 实现该接口可以使用增强for循环 ---| Collection 描述所有集合共性的接口 ---| List接口 可以有重复元素的集合 ---| Set接口 不可以有重复元素的集合 |
public interface Iterable<T>
Itreable 该接口仅有一个方法,用于返回集合迭代器对象。
1: Iterator<T> iterator() 返回集合的迭代器对象
Iterator接口定义的方法
Itreator 该接口是集合的迭代器接口类,定义了常见的迭代方法 1:boolean hasNext() 判断集合中是否有元素,如果有元素可以迭代,就返回true。 2: E next() 返回迭代的下一个元素,注意: 如果没有下一个元素时,调用 next元素会抛出NoSuchElementException
3: void remove() 从迭代器指向的集合中移除迭代器返回的最后一个元素(可选操 作)。 |
思考:为什么next方法的返回类型是Object的呢? 为了可以接收任意类型的对象,那么返回的时候,不知道是什么类型的就定义为object
1.1.3. 迭代器遍历
1:while循环
public static void main(String[] args) { ArrayList list = new ArrayList(); // 增加:add() 将指定对象存储到容器中 list.add("计算机网络"); list.add("现代操作系统"); list.add("java编程思想"); list.add("java核心技术"); list.add("java语言程序设计"); System.out.println(list); Iterator it = list.iterator(); while (it.hasNext()) { String next = (String) it.next(); System.out.println(next); } } |
2:for循环
import java.util.ArrayList; import java.util.Iterator;
public class Demo2 { public static void main(String[] args) { ArrayList list = new ArrayList(); // 增加:add() 将指定对象存储到容器中 list.add("计算机网络"); list.add("现代操作系统"); list.add("java编程思想"); list.add("java核心技术"); list.add("java语言程序设计"); System.out.println(list);
for (Iterator it = list.iterator(); it.hasNext();) { //迭代器的next方法返回值类型是Object,所以要记得类型转换。 String next = (String) it.next(); System.out.println(next); } } }
|
需要取出所有元素时,可以通过循环,java 建议使用for 循环。因为可以对内存进行一下优化。
3:使用迭代器清空集合
public class Demo1 { public static void main(String[] args) { Collection coll = new ArrayList(); coll.add("aaa"); coll.add("bbb"); coll.add("ccc"); coll.add("ddd"); System.out.println(coll); Iterator it = coll.iterator(); while (it.hasNext()) { it.next(); it.remove(); } System.out.println(coll); } } |
细节一:
如果迭代器的指针已经指向了集合的末尾,那么如果再调用next()会返回NoSuchElementException异常
import java.util.ArrayList; import java.util.Iterator;
public class Demo2 { public static void main(String[] args) { ArrayList list = new ArrayList(); // 增加:add() 将指定对象存储到容器中 list.add("计算机网络"); list.add("现代操作系统"); list.add("java编程思想"); list.add("java核心技术"); list.add("java语言程序设计"); System.out.println(list);
Iterator it = list.iterator(); while (it.hasNext()) { String next = (String) it.next(); System.out.println(next); } // 迭代器的指针已经指向了集合的末尾 // String next = (String) it.next(); // java.util.NoSuchElementException } } |
细节二:
如果调用remove之前没有调用next是不合法的,会抛出IllegalStateException
import java.util.ArrayList; import java.util.Iterator;
public class Demo2 { public static void main(String[] args) { ArrayList list = new ArrayList(); // 增加:add() 将指定对象存储到容器中 list.add("计算机网络"); list.add("现代操作系统"); list.add("java编程思想"); list.add("java核心技术"); list.add("java语言程序设计"); System.out.println(list);
Iterator it = list.iterator(); while (it.hasNext()) { // 调用remove之前没有调用next是不合法的 // it.remove(); // java.lang.IllegalStateException String next = (String) it.next(); System.out.println(next); }
} }
|
4:迭代器原理
查看ArrayList源码
private class Itr implements Iterator<E> {
int cursor = 0;
int lastRet = -1;
int expectedModCount = modCount;
public boolean hasNext() { return cursor != size(); }
public E next() { checkForComodification(); try { E next = get(cursor); lastRet = cursor++; return next; } catch (IndexOutOfBoundsException e) { checkForComodification(); throw new NoSuchElementException(); } }
public void 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(); } }
} |
5:注意在对集合进行迭代过程中,不允许出现迭代器以外的对元素的操作,因为这样会产生安全隐患,java会抛出异常并发修改异常(ConcurrentModificationException),普通迭代器只支持在迭代过程中的删除动作。
注意: ConcurrentModificationException: 当一个集合在循环中即使用引用变量操作集合又使用迭代器操作集合对象, 会抛出该异常。
import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class Demo1 { public static void main(String[] args) { Collection coll = new ArrayList(); coll.add("aaa"); coll.add("bbb"); coll.add("ccc"); coll.add("ddd"); System.out.println(coll); Iterator it = coll.iterator(); while (it.hasNext()) { it.next(); it.remove(); coll.add("abc"); // 出现了迭代器以外的对元素的操作 } System.out.println(coll); } } |
如果是List集合,想要在迭代中操作元素可以使用List集合的特有迭代器ListIterator,该迭代器支持在迭代过程中,添加元素和修改元素。