java迭代器_java 迭代器

一  概念

迭代器是一个对象,它的工作是遍历并选择序列中的对象,它提供了一种访问一个容器对象中的各个元素的方法,而不必暴露容器对象的内部细节。

作用:

1   通过迭代器,开发人员不需要了解容器结构,就可以遍历容器元素。被称为轻量级容器(创建迭代器代价很小)

2   它的特点是更加安全,因为它可以确保,在当前遍历的集合元素被更改的时候,就会抛出 ConcurrentModificationException 异常

二  用法

Java中的Iterator功能比较简单,并且只能单向移动:

(1) 使用方法iterator()要求容器返回一个Iterator对象。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。

(2) 使用next()获得序列中的下一个元素。

(3) 使用hasNext()检查序列中是否还有元素。

(4) 使用remove()将迭代器新返回的元素删除。

简单例子

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

import java.util.*;public classMuster {public static voidmain(String[] args) {

ArrayList list= newArrayList();

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);

}

}

}

View Code

三  迭代器是失效问题(删除或新增元素)

在创建迭代器之后,除非通过迭代器自身的remove 或add 方法从结构上对列表进行修改,否则在任何时间以任何方式对列表进行修改,迭代器都会抛出ConcurrentModificationException。

public classArrayListTest {public static voidmain(String args[])

{

List strList = new ArrayList();//迭代器

Iterator iterator = strList.iterator();//修改了集合

for (int i = 0; i < 10; i++)

{

strList.add("string" +i);

}while(iterator.hasNext())

{

System.out.println(iterator.next());

}

}

运行该段代码,会发现其抛出如下异常:

Exception in thread "main" java.util.ConcurrentModificationException

at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)

at java.util.AbstractList$Itr.next(AbstractList.java:343)

at com.xyh.collection.ArrayListTest.main(ArrayListTest.java:21)

原因在于在迭代器创建之后,通过ArrayList自身的add方法对列表进行了修改,导致迭代器失效。当将蓝色创建迭代器的代码移动到while循环的上方后,则不会出现该问题。即创建迭代器后不能再通过容器的add/remove方法来改变容器的数据,否则会导致迭代器的失效。

包括下面这种写法,也是会导致同样的异常

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public static voidmain(String[] args) {

List list = new ArrayList();

list.add("a");

list.add("b");

list.add("c");

list.add("d");

list.add("e");

list.add("f");

list.add("g");

list.add("h");

Iterator it =list.iterator();while(it.hasNext()) {

String str=it.next();if (str.equals("f")) {

list.remove(str);

}

}

}

View Code

上面异常的本质是

remove操作里涉及到的expectedModCount = modCount;  值为调用容器的iterator()方法返回iterator对象时,容器中的元素个数

在网上查到说这是集合迭代中的一种“快速失败”机制,这种机制提供迭代过程中集合的安全性。

从源代码里可以看到增删操作都会使modCount++,通过和expectedModCount的对比,迭代器可以快速的知道迭代过程中是否存在list.add()类似的操作,存在的话快速失败!

而我们也知道,集合元素的删除,不能用foreach  这又是为什么?

foreach中的remove方法实际上使用list.remove一样会报ConcurrentModificationException异常。因为foreach在jvm中还是会解析成Iterator来执行的,实际上和错误例子是一样的效果。

那么,我们再来看下为什么用迭代器删除时就可以安全的删除,不会报错呢?

在他的remove函数中可以看到下面的一句话,首先其实还是调用了ArrayList的remove函数

ArrayList.this.remove(lastRet)

但是在调用完该函数后,他又进行了如下操作

expectedModCount = modCount;

相当于将最新的版本号告诉了迭代器,所以迭代器在进行异常检查的时候就不会报错,因为他俩是相等的

四  迭代器删除元素

public classArrayListTest {public static voidmain(String args[]) throws Exception

{

List strList = new ArrayList();for (int i = 0; i < 10; i++)

{

strList.add("string" +i);

}

Iterator iterator =strList.iterator();while(iterator.hasNext())

{//iterator.next() 游标指向了下一个元素

if (iterator.next().equals("string3"))

{

iterator.remove();//iterator.remove()移除的是最近一次iterator.next()所获取的对象

}

}

iterator=strList.iterator();while(iterator.hasNext())

{

System.out.println(iterator.next());

}

}

}

上述代码中,iterator.remove操作移除的对象时string3。如果将蓝色while循环替换为如下的代码:

int index = 0;while(iterator.hasNext())

{if (++index == 3)

{

iterator.remove();

}

System.out.println(iterator.next());

本代码的初衷是希望通过使用迭代器来删除第三个元素即string2,并将未删除的元素依次打印出来,殊不知删除的却是string1元素,即:iterator.remove()操作删除的是上一次next元素获取的对象。因此在这里可以发现,如果要通过迭代器删除一个元素,首先要通过next方法获取该元素。

需要删除元素,也可以把迭代器遍历过程中,把需要删除的元素放入新集合,遍历完成后一次性删除  removeAll()

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值