常见Java集合实现细节——Iterator迭代器

来源:互联网 发布:linux开启端口监听 编辑:程序博客网 时间:2024/05/24 07:40

4、Iterator迭代器

       Iterator是一个迭代器接口,专门用于迭代器各种Collection集合,包括Set集合和List集合。

4、1 Iterator实现类与迭代器模式

import java.util.ArrayDeque;import java.util.ArrayList;import java.util.EnumSet;import java.util.HashSet;import java.util.LinkedHashSet;import java.util.LinkedList;import java.util.TreeSet;import java.util.Vector;enum Sex{FEMALE , MALE;}public class IteratorTest {public static void main(String[] args) {HashSet<String> hashSet = new HashSet<>();System.out.println("HashSet的Iterator:" + hashSet.iterator());LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();System.out.println("LinkedHashSet的Iterator:" + linkedHashSet.iterator());TreeSet<String> treeSet = new TreeSet<>();System.out.println("TreeSet的Iterator:" + treeSet.iterator());EnumSet<Sex> enumSet = EnumSet.allOf(Sex.class);System.out.println("EnumSet的Iterator:" + enumSet.iterator());ArrayList<String> arrayList = new ArrayList<>();System.out.println("ArrayList的Iterator:" + arrayList.iterator());Vector<String> vector = new Vector<>();System.out.println("Vector的Iterator:" + vector.iterator());LinkedList<String> linkedList = new LinkedList<>();System.out.println("LinkedList的Iterator:" + linkedList.iterator());ArrayDeque<String> arrayDeque = new ArrayDeque<>();System.out.println("ArrayDeque的Iterator:" + arrayDeque.iterator());}}
输出结果为:
HashSet的Iterator:java.util.HashMap$KeyIterator@2a36bb87
LinkedHashSet的Iterator:java.util.LinkedHashMap$KeyIterator@5511e28
TreeSet的Iterator:java.util.TreeMap$KeyIterator@2198a037
EnumSet的Iterator:java.util.RegularEnumSet$EnumSetIterator@119fdafc
ArrayList的Iterator:java.util.ArrayList$Itr@1b219665
Vector的Iterator:java.util.Vector$Itr@3a18cecd
LinkedList的Iterator:java.util.LinkedList$ListItr@2e4f7bc2
ArrayDeque的Iterator:java.util.ArrayDeque$DeqIterator@15136019
       从上面运行的结果可以看出,除了EnumSet集合的Iterator就是RegularEnumSet的一个内部类之外,所有Set集合对应的Iterator都是它对应的Map类的内部类KeyIterator。这是因为,Set集合底层是通过Map来实现的。
       通过上面的介绍可以得出,对应Iterator迭代器而言,它仅仅只是一个接口。Java要求各种集合都提供一个iterator()方法,该方法可以返回一个Iterator用于遍历该集合中的元素,至于返回的Iterator到底是哪种实现类,程序并不关心,这就是定性的“迭代器模式”。
提示:迭代器模式指的是:系统为遍历多种数据列表、集合、容器提供一个标准的“迭代器接口”,这些数据列表、集合、容器就可面向相同的“迭代器接口”编程,通过相同的迭代器接口访问不同数据列表、集合、容器里的数据。不同的数据列表、集合、容器如何实现这个“迭代器接口”,则交给各数据列表、集合、容器自己完成。

4、2 迭代时删除指定的元素

       由于Iterator迭代器只负责对各种集合中所包含的元素进行迭代,但迭代器本身并没有保留集合元素,因此使用Iterator进行迭代时,通常不应该删除集合元素,否则将引发ConcurrentModificationException异常。当然,Java允许通过Iterator提供的remove()方法删除刚刚迭代的集合元素。
import java.util.ArrayList;import java.util.Iterator;public class ArrayListRemove {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();list.add("123");list.add("456");list.add("789");for ( Iterator<String> it = list.iterator() ; it.hasNext() ; ) {String e = it.next();System.out.println(e);if ( e.equals("456") ) {  //①list.remove(e);}}}}
输出结果:
123
456
       上面程序中直接调用了List的remove()方法删除指定的集合元素。运行上面的程序,发现该程序完全可以正常结束,并未引发任何异常。
       实际上,对于ArrayList、Vector、LinkedList等List集合而言,当使用Iterator遍历时,如果正在遍历倒数第二个集合元素,那么使用List结合的remove()方法删除集合的任意一个元素并不会引发ConcurrentModificationException异常,当正在遍历其他元素时删除其他元素就会引发该异常。也就是说,如果将程序中的①行代码改为等于其他元素,就会引发ConcurrentModificationException异常。
import java.util.Iterator;import java.util.TreeSet;public class TreeSetRemove {public static void main(String[] args) {TreeSet<String> set = new TreeSet<>();set.add("123");set.add("456");set.add("789");for ( Iterator<String> it = set.iterator() ; it.hasNext() ; ) {String e = it.next();System.out.println(e);if ( e.equals("789") ) {  //①set.remove(e);}}}}
输出结果为:
123
456
789
       上面程序中尝试了使用Iterator遍历TreeSet集合时,直接调用Set的remove()方法删除指定的集合元素。运行上面程序,发现该程序完全可以正常结束,并未引发任何异常。
       对于TreeSet、HashSet等Set集合而言,当使用Iterator遍历时,如果正在遍历最后一个元素,那么使用Set集合的remove()方法删除集合的任意元素并不会引发ConcurrentModificationException异常,当正在遍历其他元素时删除集合的任意元素都引发异常。也就是说,如果将程序中的①行代码改为等于其他元素,就会引发ConcurrentModificationException异常。

       为何使用Iterator遍历List集合的倒数第二个元素时,直接使用List集合的remove()方法删除List集合的倒数第二个元素没有引发异常呢?关键在于List集合对应的Iterator实现类(Itr)的hasNext()方法。
//Iterator实现类(Itr)源代码public boolean hasNext() {    return cursor != size;}
       对于Itr遍历器而言,判断是否还有下一个元素的标准是:如果下一步即将访问的元素的索引不等于集合的大小,返回true,否则返回false。当程序使用Iterator遍历List集合的倒数第二个元素时,下一步即将访问的元素的索引为size()-1。如果此时通过List删除集合的任意一个元素,则将导致集合的size()变为size()-1,这将导致hasNext()方法返回false。也就是说,遍历提前结束,Iterator不会访问List集合的最后一个元素。
       类似地,对于Set集合而言,如果当前正在遍历集合的最后一个元素,也就是集合遍历操作已经完成,此时删除Set集合的任意元素都将不会引发异常。



1 0
原创粉丝点击