李林超博客
首页
归档
留言
友链
动态
关于
归档
留言
友链
动态
关于
首页
Java
正文
持有对象--迭代器
Leefs
2019-12-02 AM
3324℃
2条
# 持有对象--迭代器 ### 前言 任何容器类,都必须有某种方式可以插入元素并将它们再次取回。毕竟,持有事物是容器最基本的工作。 对于List容器,add():插入元素,get():取出元素。 如果从更高层的角度考虑,会发现这里有个缺点:**要使用容器,必须对容器的确切类型编程**。初看起来这没什么不好,但是考虑下面的情况:如果原本是对着List编码的,但是后来发现如果能够把相同的代码应用于Set,将会显得非常方便,此时应该怎么做?或者打算从头开始编写通用的代码,它们只是使用容器,不知道或者不关心容器的类型,那么如何才能不重写代码就可以应用于不同类型的容器? ### 概念 迭代器(也是一种设计模式)的概念可以用于达成此目的。 **迭代器模式:就是提供一种方法对一个容器对象中的各个元素进行访问,而又不暴露该对象容器的内部细节。** Java集合框架的集合类,我们有时候称之为容器。容器的种类有很多种,比如`ArrayList`、`LinkedList`、`HashSet`...,每种容器都有自己的特点,`ArrayList`底层维护的是一个数组;`LinkedList`是链表结构的;`HashSet`依赖的是哈希表,每种容器都有自己特有的数据结构。 因为容器的内部结构不同,很多时候可能不知道该怎样去遍历一个容器中的元素。所以为了使对容器内元素的操作更为简单,Java引入了迭代器模式! 把访问逻辑从不同类型的集合类中抽取出来,从而避免向外部暴露集合的内部结构。 ### 参数说明 迭代器通常被称为轻量级对象:创建它的代价小,因此,经常可以见到对迭代器有些奇怪的限制:例如,Java的Iterator只能单向移动,这个Iterator只能用来: > 1.使用方法iterator()要求容器返回一个Iterator。Iterator将准备好返回序列的第一个元素 > > 2.使用next()获得序列中的下一个元素。 > > 3.使用hasNext()检查序列中是否还有元素。 > > 4.使用remove()将迭代器新返回的元素删除 ```java public class SimpleIteratoion { public static void main(String[] args) { List
pets = Pets.arrayList(12); Iterator
it = pets.iterator(); while(it.hasNext()){ Pet p = it.next(); System.out.print(p.id() +":"+p+" "); } System.out.println(); for(Pet p : pets){ System.out.print(p.id() + ":"+p+" "); } System.out.println(); it=pets.iterator(); for(int i = 0; i<6;i++){ it.next(); it.remove(); } System.out.println(pets); } } ``` > 运行结果 ```java 0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx 8:Cymric 9:Rat 10:EgyptianMau 11:Hamster 0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx 8:Cymric 9:Rat 10:EgyptianMau 11:Hamster [Pug, Manx, Cymric, Rat, EgyptianMau, Hamster] ``` 有了Iterator就不必为容器中元素的数量操心了,那是由`hasNext()`和`next()`关心的事情。 如果你只是向前遍历List,并不打算修改List对象本身,那么你可以看到`foreach`语法会显得更加简洁。 Iterator还可以移除由next()产生的最后一个元素,这意味着在调用remove()之前必须先调用next(). **接受对象容器并传递它,从而在每个对象上都执行操作,这种思想十分强大,事实上,你工作中的很大一部分时间就是在做该操作。** ### 代码2 现在考虑创建一个display()方法,它不必知晓容器的确切类型: ```java public class CrossContainerIteration { public static void display(Iterator
it){ while(it.hasNext()){ Pet p = it.next(); System.out.print(p.id() + ":" + p + " "); } System.out.println(); } public static void main(String[] args) { ArrayList
pets = Pets.arrayList(8); LinkedList
petsLL = new LinkedList
(pets); HashSet
petsHS = new HashSet
(pets); TreeSet
petsTS = new TreeSet
(pets); display(pets.iterator()); display(petsLL.iterator()); display(petsHS.iterator()); display(petsTS.iterator()); } } ``` > 运行结果 ```java 0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx 0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx 0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx 5:Cymric 2:Cymric 7:Manx 1:Manx 3:Mutt 6:Pug 4:Pug 0:Rat ``` display()方法不包含任何有关它所遍历的序列的类型信息,而这也展示了Iterator的真正威力:能够将遍历序列的操作与序列底层的结构分离。 正由于此,我们有时会说:迭代器统一了对容器的访问方式。 ### 练习题 > 写一个方法,使用Iterator遍历Collection,并打印容器中每个对象的`toString()`。填充各种类型的Collection,然后对其使用此方法。 ```java public class containerTest11 { public static void display(Collection c){ Iterator it = c.iterator(); while(it.hasNext()){ System.out.print(it.next()+" "); } } public static void main(String[] args) { List
a = new ArrayList<>( Arrays.asList("aa","bb","cc") ); display(a); } } ``` > 运行结果 ```java aa bb cc ```
标签:
Java
,
Java编程思想
,
JavaSE
,
持有对象
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:
https://lilinchao.com/archives/245.html
上一篇
JVM学习(十)--ClassLoader源码解析与实例剖析
下一篇
迭代器--ListIterator
评论已关闭
栏目分类
随笔
2
Java
326
大数据
229
工具
31
其它
25
GO
47
NLP
4
标签云
Nacos
Kafka
Git
并发线程
MyBatisX
栈
gorm
Thymeleaf
Http
序列化和反序列化
MySQL
SpringBoot
设计模式
Docker
Hive
Shiro
前端
Python
字符串
链表
Hbase
JVM
Map
持有对象
并发编程
JavaScript
nginx
Hadoop
Eclipse
BurpSuite
友情链接
申请
范明明
庄严博客
Mx
陶小桃Blog
虫洞
评论已关闭