常见Java集合实现细节——Iterator迭代器
2017-04-19 08:55
302 查看
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集合的任意元素都将不会引发异常。
相关文章推荐
- 常见java集合的实现细节
- 常见Java集合的实现细节(一)
- 常见Java集合实现细节——List集合与Map集合
- 常见Java集合实现细节——ArrayList和LinkedList
- Java集合的实现细节【1】——Set集合和Map集合
- Java集合的实现细节—Set集合和Map集合
- Java集合实现细节
- 深入Java集合学习系列:ConcurrentHashMap之实现细节
- Java常见集合例题(1、集合的嵌套遍历。2、获取随机数。3三种方式实现对集合中存储对象的遍历)
- 程序员的基本功之Java集合的实现细节
- 论JAVA集合的实现细节,Map和List的联系
- Java实现Map集合遍历的四种常见方式与用法分析
- Java之集合的实现细节(一)
- java集合之间的关系及实现细节(1)——Set与Map
- 【疯狂Java_突破程序员基本功的16课】charpt3 常见Java集合的实现机制
- Java集合实现细节
- 3 Java 集合的实现细节
- 用Java实现几种常见的排序算法
- JAVA基础笔试、面试常见问题集合
- 用Java实现几种常见的排序算法