Java迭代器(iterator详解以及和for循环的区别)

觉得有用的话,欢迎一起讨论相互学习~[Follow]

前言

  • 迭代器是一种模式、详细可见其设计模式,可以使得序列类型的数据结构的遍历行为与被遍历的对象分离,即我们无需关心该序列的底层结构是什么样子的。只要拿到这个对象,使用迭代器就可以遍历这个对象的内部
  • Iterable 实现这个接口的集合对象支持迭代,是可以迭代的。实现了这个可以配合foreach使用~
  • Iterator 迭代器,提供迭代机制的对象,具体如何迭代是这个Iterator接口规范的。
//Iterable JDK源码
//可以通过成员内部类,方法内部类,甚至匿名内部类去实现Iterator public interface Iterable<T>
{ Iterator<T> iterator();
  • Iterable还有一个默认的方法forEach()
  • 而Iterator接口:包含三个方法:hasNext,next,remove、remove一般很少用到.

public interface Iterator<E> { boolean hasNext(); //每次next之前,先调用此方法探测是否迭代到终点 E next(); //返回当前迭代元素 ,同时,迭代游标后移 /*删除最近一次已近迭代出出去的那个元素。
只有当next执行完后,才能调用remove函数。
比如你要删除第一个元素,不能直接调用 remove() 而要先next一下( );
在没有先调用next 就调用remove方法是会抛出异常的。
这个和MySQL中的ResultSet很类似
*/
void remove()
{
throw new UnsupportedOperationException("remove");
}

Note

  • 迭代出来的元素都是原来集合元素的拷贝。
  • Java集合中保存的元素实质是对象的引用,而非对象本身。
  • 迭代出的对象也是引用的拷贝,结果还是引用。那么如果集合中保存的元素是可变类型的,那么可以通过迭代出的元素修改原集合中的对象。
import java.util.ArrayList;
import java.util.Iterator; public class test {
public static void main(String[] args) {
ArrayList<Person> array = new ArrayList<Person>(); Person p1 = new Person("Tom1");
Person p2 = new Person("Tom2");
Person p3 = new Person("Tom3");
Person p4 = new Person("Tom4"); array.add(p1);
array.add(p2);
array.add(p3);
array.add(p4); Iterator<Person> iterator = array.iterator(); for (Person pp : array){
System.out.println(pp.getName());
} System.out.println("\r\n" + "-----利用Lambda表达式的foreach-----" + "\r\n");
array.forEach(obj -> System.out.println(obj.getName())); System.out.println("\r\n" + "-----利用for循环-----" + "\r\n");
for(Person p : array){
p.setName("wang");
} while(iterator.hasNext()){
System.out.println(iterator.next().getName()); //输出的是wang,而不是tom
} }
}

Map遍历也是一样的~

public static void main(String[] args) {
Map map = new HashMap();
for(int i = 0; i < 10; i ++){
map.put(i, String.valueOf("map" + i));
}
Iterator iterMap = map.entrySet().iterator();
while(iterMap.hasNext()){
Map.Entry strMap = (Map.Entry)iterMap.next();
System.out.println("key为:" + strMap.getKey() +
", value为:" + strMap.getValue());
}
}

那么当Iterator迭代访问Collection集合中元素时,Collection的元素不能改变(多个线程的修改),只有通过Iterator的remove()方法删除上一次next()方法返回集合才可以。这样会引发ModificationException异常,即fail-fast机制

//创建集合,添加元素和上述一样
        Iterator<Person> iterator = array.iterator(); while(iterator.hasNext()){
String name = iterator.next().getName();
System.out.println(name);
if(name.equals("Tom3")){
//array.remove(name); 不推荐这种方式
iterator.remove();
}
}

Iterator与泛型搭配:

  • Iterator对集合类中的任何一个实现类,都可以返回这样一个Iterator对象。可以适用于任何一个类。
  • 因为集合类(List和Set等)可以装入的对象的类型是不确定的,从集合中取出时都是Object类型,用时都需要进行强制转化,这样会很麻烦,用上泛型,就是提前告诉集合确定要装入集合的类型,这样就可以直接使用而不用显示类型转换.非常方便.

foreach和Iterator的关系:

  • for each以用来处理集合中的每个元素而不用考虑集合定下标。就是为了让用Iterator简单。但是删除的时候,区别就是在remove,循环中调用集合remove会导致原集合变化导致错误,而应该用迭代器的remove方法。

使用for循环还是迭代器Iterator对比

  • 采用ArrayList对随机访问比较快,而for循环中的get()方法,采用的即是随机访问的方法,因此在ArrayList里,for循环较快
  • 采用LinkedList则是顺序访问比较快,iterator中的next()方法,采用的即是顺序访问的方法,因此在LinkedList里,使用iterator较快
  • 从数据结构角度分析,for循环适合访问顺序结构,可以根据下标快速获取指定元素.而Iterator 适合访问链式结构,因为迭代器是通过next()和Pre()来定位的.可以访问没有顺序的集合.
  • 而使用 Iterator 的好处在于可以使用相同方式去遍历集合中元素,而不用考虑集合类的内部实现(只要它实现了 java.lang.Iterable 接口),如果使用 Iterator 来遍历集合中元素,一旦不再使用 List 转而使用 Set 来组织数据,那遍历元素的代码不用做任何修改,如果使用 for 来遍历,那所有遍历此集合的算法都得做相应调整,因为List有序,Set无序,结构不同,他们的访问算法也不一样.(还是说明了一点遍历和集合本身分离了)

[转载]Java迭代器(iterator详解以及和for循环的区别)的更多相关文章

  1. python——iterator迭代器|iterator详解——20140918|

    -----------------------------------------------------------------------------前言--------------------- ...

  2. java集合框架详解

    java集合框架详解 一.Collection和Collections直接的区别 Collection是在java.util包下面的接口,是集合框架层次的父接口.常用的继承该接口的有list和set. ...

  3. Java集合类的详解与应用

    Java集合类的详解与应用 集合简介: 1.定义:可以同时存储不同类型的数据 他的存储空间会随着数据的增大而增大 2.缺点:只能存储引用数据类型 3.优点:更加合理的利用空间,封装了更多的方法,用起来 ...

  4. 最强Java并发编程详解:知识点梳理,BAT面试题等

    本文原创更多内容可以参考: Java 全栈知识体系.如需转载请说明原处. 知识体系系统性梳理 Java 并发之基础 A. Java进阶 - Java 并发之基础:首先全局的了解并发的知识体系,同时了解 ...

  5. Java 字符串格式化详解

    Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...

  6. Java 序列化Serializable详解

    Java 序列化Serializable详解(附详细例子) Java 序列化Serializable详解(附详细例子) 1.什么是序列化和反序列化Serialization(序列化)是一种将对象以一连 ...

  7. 转:Java HashMap实现详解

    Java HashMap实现详解 转:http://beyond99.blog.51cto.com/1469451/429789 1.    HashMap概述:    HashMap是基于哈希表的M ...

  8. 设计模式 - 迭代模式(iterator pattern) Java 迭代器(Iterator) 详细解释

    迭代模式(iterator pattern) Java 迭代器(Iterator) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 參考迭代器模式(ite ...

  9. Java 枚举(enum) 详解7种常见的用法

    Java 枚举(enum) 详解7种常见的用法 来源 https://blog.csdn.net/qq_27093465/article/details/52180865 JDK1.5引入了新的类型— ...

随机推荐

  1. git教程——简单总结

    1 创建版本库: 初始化一个Git仓库,使用git init命令. 添加文件到Git仓库,分两步: (1)使用命令git add <file>,注意,可反复多次使用,添加多个文件: (2) ...

  2. 十七.protobuf在rpc中的使用

    关于protobuf在rpc中的使用,设计到gRPC,相关内容待续....

  3. Django上传文件和修改date格式

    上传大文件的时候: 修改date数据:

  4. bug的编写技巧与级别划分

    一.bug编写技巧 确.清晰.简洁.完整.一致 二.bug包含的要素 缺陷ID.缺陷标题.测试环境.缺陷发现日期时间.缺陷提交人 缺陷优先级.缺陷严重等级.发现缺陷软件版本.测试类型 缺陷复现步骤.期 ...

  5. LightOJ - 1236 - Pairs Forming LCM(唯一分解定理)

    链接: https://vjudge.net/problem/LightOJ-1236 题意: Find the result of the following code: long long pai ...

  6. Ubuntu 系统安装ssh的命令

    更新源列表 打开"终端窗口",输入"sudo apt-get update"-->回车-->"输入当前登录用户的管理员密码"-- ...

  7. Kafka 幂等生产者和事务生产者特性(讨论基于 kafka-python | confluent-kafka 客户端)

    Kafka 提供了一个消息交付可靠性保障以及精确处理一次语义的实现.通常来说消息队列都提供多种消息语义保证 最多一次 (at most once): 消息可能会丢失,但绝不会被重复发送. 至少一次 ( ...

  8. SignalR要求_转自:https://www.cnblogs.com/humble/p/3855137.html

    SignalR 服务端组件可以被部署在诸多的服务器配置中,本节描述了它所支持的操作系统版本,.NET framework,IIS.以及其他组件 二.支持的服务器操作系统 SignalR服务端组件可以被 ...

  9. CORS & CSP笔记

    1.CORS & CSP 浏览器跨域相关的安全策略主要存在于两个方面: 浏览器是否发送ajax 浏览器是否加载返回数据 假设从a.com 向b.com发送ajax请求.此时浏览器当前页面为a. ...

  10. Windows 实例远程桌面报错“没有远程桌面授权服务器可以提供许可证”

    参考阿里云帮助文档: https://help.aliyun.com/knowledge_detail/40859.html?spm=5176.10695662.1996646101.searchcl ...