李林超博客
首页
归档
留言
友链
动态
关于
归档
留言
友链
动态
关于
首页
Java
正文
持有对象--适配器方法惯用法
Leefs
2019-12-13 AM
3993℃
4条
# 持有对象--适配器方法惯用法 ### 前言 本篇讲述《Java编程思想》第11.13.1小节,适配器方法惯用法 ### 一、Iterator和Iterable的区别和联系 > + 1.Iterable接口:从继承结构中可以看出,Iterable接口是Collection的顶层接口,所以Iterable是数据结构,用来存放数据的地方。 > > + 2.Iterator接口:是定义了迭代逻辑的接口,即:用于遍历Collection(集合类)中数据的标准访问方法 ![Iterator和Iterable区别01.png][1] ### 二、适配器方法惯用法 如果现有一个`Iterable`类,你想要添加一种或多种在`foreach`语句中使用这个类的方法,应该怎么做呢?例如,假设你希望可以选择以向前的方向或是向后的方向迭代一个单词列表。如果直接继承这个类,并覆盖iterator()方法,你只能替换现有的方法,而不能实现选择。 一种解决方法是所谓适配器方法的惯用法。在默认的前向的迭代器的基础上,添加产生反向迭代器的能力,我们不能使用覆盖,而是应该添加一个能够产生Iterable对象的方法,该对象可以用于foreach语句。 ```java class ReversibleArrayList
extends ArrayList
{ public ReversibleArrayList(Collection
c){ super(c); } public Iterable
reversed() {//返回一个具有反向迭代器的Iterable return new Iterable
() { public Iterator
iterator() { return new Iterator
() { int current = size() - 1; public boolean hasNext() { return current > -1; } public T next() { return get(current--); } public void remove() { // Not implemented throw new UnsupportedOperationException(); } }; } }; } } public class AdapterMethodIdiom { public static void main(String[] args) { ReversibleArrayList
ral = new ReversibleArrayList
(Arrays.asList("To be or not to be".split(" "))); for(String s:ral){ System.out.print(s+" "); } System.out.println(); for(String s:ral.reversed()) System.out.print(s+" "); } } ``` > 运行结果 ```java To be or not to be be to not or be To ``` 如果直接将ral对象置于foreach语句中,将得到(默认的)前向迭代器。但是如果在该对象上调用reversed()方法,就会产生不同的行为。 通过使用这种方式,可以在IterableClass.java中添加两种适配器方法: ```java public class MultiIterableClass extends IterableClass{ public Iterable
reversed(){ return new Iterable
(){ public Iterator
iterator(){ return new Iterator
(){ int current = words.length - 1; public boolean hasNext(){ return current > -1; } public String next(){ return words[current--]; } public void remove(){ throw new UnsupportedOperationException(); } }; } }; } public Iterable
randomized(){ return new Iterable
(){ public Iterator
iterator(){ List
shuffled = new ArrayList
(Arrays.asList(words)); Collections.shuffle(shuffled,new Random(47)); return shuffled.iterator(); } }; } public static void main(String[] args) { MultiIterableClass mic = new MultiIterableClass(); for(String s:mic.reversed()){ System.out.print(s+" "); } System.out.println(); for(String s:mic.randomized()) System.out.print(s+" "); System.out.println(); for(String s:mic){ System.out.print(s+" "); } } } ``` > 运行结果 ```java banana-shaped be to Earth the know we how is that And is banana-shaped Earth that how the be And we know to And that is how we know the Earth to be banana-shaped ``` 程序中第二个方法random()没有创建它自己的Iterator,而是直接返回被打乱的List中的Iterator。 从输出中可以看出,Collection.shuffle()方法没有影响到原来的数组,而只是打乱了shuffled中的引用。之所以这样,只是因为randomized方法用一个ArrayList将Arrays.asList()方法的结果包装了起来。如果这个由Arrays.asList()方法产生的List被直接打乱,那么它就会修改底层的数组,就像下面的这样: ```java public class ModifyingArraysAsList { public static void main(String[] args) { Random random = new Random(); Integer[] ia = {1,2,3,4,5,6,7,8,9,10}; List
list1 = new ArrayList
(Arrays.asList(ia)); System.out.println("Before shuffling:"+list1); Collections.shuffle(list1,random); System.out.println("After shuffling:"+list1); System.out.println("array:"+Arrays.toString(ia)); List
list2 = Arrays.asList(ia); System.out.println("Before shuffling:"+list2); Collections.shuffle(list2,random); System.out.println("After shuffling:"+list2); System.out.println("array:"+Arrays.toString(ia)); } } ``` > 运行结果 ```java Before shuffling:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] After shuffling:[8, 9, 1, 7, 2, 5, 4, 6, 10, 3] array:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] Before shuffling:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] After shuffling:[6, 9, 3, 10, 8, 4, 2, 1, 7, 5] array:[6, 9, 3, 10, 8, 4, 2, 1, 7, 5] ``` 在第一种情况中,Arrays.asList()的输出被传递给了ArrayList()的构造器,这将创建一个引用ia的元素的ArrayList,因此打乱这些引用不会修改该数组。但是,如果直接使用Arrays.asList(a)的结果,这种打乱就会修改ia的顺序。 [1]: https://lilinchao.com/usr/uploads/2019/12/1273697601.png
标签:
Java
,
Java编程思想
,
JavaSE
,
持有对象
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:
https://lilinchao.com/archives/281.html
上一篇
持有对象--Foreach与迭代器
下一篇
持有对象--总结
取消回复
评论啦~
提交评论
已有 4 条评论
茂林
好多底层,真香
回复
2019-12-16 09:18
Leefs
博主
@茂林
是吧
回复
2019-12-17 23:09
茂林
大佬牛批
回复
2019-12-14 09:52
Leefs
博主
@茂林
我是最菜的了
回复
2019-12-15 09:32
栏目分类
随笔
2
Java
326
大数据
229
工具
31
其它
25
GO
47
标签云
容器深入研究
LeetCode刷题
国产数据库改造
Redis
Linux
MyBatisX
JavaWeb
前端
BurpSuite
JavaScript
Golang基础
MyBatis
Hbase
队列
栈
JavaSE
并发编程
NIO
Spark
Spark Streaming
Spark SQL
ClickHouse
机器学习
Elastisearch
序列化和反序列化
SpringCloud
Eclipse
CentOS
Flume
递归
友情链接
申请
范明明
庄严博客
Mx
陶小桃Blog
虫洞
好多底层,真香
是吧
大佬牛批
我是最菜的了