如果现在有一个Iterable类,你想要添加一种或多种在foreach语句中使用这个类的方法,例如方向迭代,应该怎么做呢? 如果之间继承这个类,并且覆盖iterator()方法,你只能替换现有的方法,而不能实现选择

一种解决方案是所谓的adapter方法的惯用法,"适配器"部分来自于设计模式,因为你必须提供特定接口以满足foreach语句,当你有一个接口并需要另一个接口时,编写adapter就可以解决问题,这里,希望在默认的前向迭代器的基础上,添加方向迭代器的能力,因此不能使用覆盖,而是添加了一个能够产生Iterable对象的方法,该对象可以用于foreach语句,正如你所见,可以提供多种使用foreach的方式

package object;
//: holding/AdapterMethodIdiom.java
// The "Adapter Method" idiom allows you to use foreach
// with additional kinds of Iterables.
import java.util.*; class ReversibleArrayList<T> extends ArrayList<T> {
public ReversibleArrayList(Collection<T> c) { super(c); }
public Iterable<T> reversed() {//返回一个具有反向迭代器的Iterable
return new Iterable<T>() {
public Iterator<T> iterator() {
return new Iterator<T>() {
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<String> ral =
new ReversibleArrayList<String>(
Arrays.asList("To be or not to be".split(" ")));
// Grabs the ordinary iterator via iterator():
for(String s : ral)
System.out.print(s + " ");
System.out.println();
// Hand it the Iterable of your choice
for(String s : ral.reversed())
System.out.print(s + " ");
}
} /* Output:
To be or not to be
be to not or be To
*///:~

通过这种方法,可以在IterableClass.java的示例中添加两种适配器方法

package object;
//: holding/MultiIterableClass.java
// Adding several Adapter Methods.
import java.util.*; public class MultiIterableClass extends IterableClass {
public Iterable<String> reversed() {
return new Iterable<String>() {
public Iterator<String> iterator() {
return new Iterator<String>() {
int current = words.length - 1;
public boolean hasNext() { return current > -1; }
public String next() { return words[current--]; }
public void remove() { // Not implemented
throw new UnsupportedOperationException();
}
};
}
};
}
public Iterable<String> randomized() {
return new Iterable<String>() {
public Iterator<String> iterator() {
List<String> shuffled =
new ArrayList<String>(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 + " ");
}
} /* Output:
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.
*///:~
Collections方法并没有打乱原来的数组,而是打乱了shuffled中的引用,之所以这样,只是因为,randmize()方法用一个ArrayList将Arrays.asList()结果包装了起来
如果这个有Arrays.asList()产生的List被直接打乱,那么就会修改底层是数组,就像下面这样;
package object;
//: holding/ModifyingArraysAsList.java
import java.util.*; public class ModifyingArraysAsList {
public static void main(String[] args) {
Random rand = new Random(47);
Integer[] ia = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
List<Integer> list1 =
new ArrayList<Integer>(Arrays.asList(ia));//ia的输出被传给了ArrayList构造器,这将创建一个ia的元素引用的ArrayList
System.out.println("Before shuffling: " + list1);
Collections.shuffle(list1, rand);
System.out.println("After shuffling: " + list1);
System.out.println("array: " + Arrays.toString(ia)); List<Integer> list2 = Arrays.asList(ia);//lsit2 直接使用Arrays.asList(ia),这样做会直接修改ia的数据
System.out.println("Before shuffling: " + list2);
Collections.shuffle(list2, rand);
System.out.println("After shuffling: " + list2);
System.out.println("array: " + Arrays.toString(ia));
}
} /* Output:
Before shuffling: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
After shuffling: [4, 6, 3, 1, 8, 7, 2, 5, 10, 9]
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: [9, 1, 6, 3, 7, 2, 5, 10, 4, 8]
array: [9, 1, 6, 3, 7, 2, 5, 10, 4, 8]
*///:~

意识到Arrays.asLIst()产生的对象会使用底层数组作为其物理实现是很重要的,只要你执行的操作会修改这个List,并且你不想原来的数组被修改那么你就应该在另一个容器中创建副本

java adapter(适配器)惯用方法的更多相关文章

  1. Android中ListView 控件与 Adapter 适配器如何使用?

    一个android应用的成功与否,其界面设计至关重要.为了更好的进行android ui设计,我们常常需要借助一些控件和适配器.今天小编在android培训网站上搜罗了一些有关ListView 控件与 ...

  2. GoldenGate for Java Adapter介绍一(原理篇)

    前言 Oracle Goldengate在很早前就推出了一个for java的版本,主要目的是方便把关系型数据实时写入到不支持的目标端,如JMS或Redis等key value数据库.在Hadoop刚 ...

  3. java演示适配器(adapter)模式

    为什么要使用模式: 模式是一种做事的一种方法,也即实现某个目标的途径,或者技术. adapter模式的宗旨就是,保留现有类所提供的服务,向客户提供接口,以满足客户的需求. 类适配器:客户端定义了接口并 ...

  4. Java 实现适配器(Adapter)模式

    平时我们会常常碰到这种情况,有了两个现成的类,它们之间没有什么联系.可是我们如今既想用当中一个类的方法.同一时候也想用另外一个类的方法.有一个解决方法是.改动它们各自的接口.可是这是我们最不愿意看到的 ...

  5. Android adapter适配器的学习

    学习Android有一点时间,说说自己的学习感悟. 首先呢,先说说适配器的作用,顾名思义,它就是把数据定义好一定的规则,使得我们可以用到ListView GridView等上面 所以说这玩意,还是得好 ...

  6. Android adapter适配器的使用

    说起Adapter的使用,首先想到的就是listview或各种各样的Adapter.下面我们对常用的一些Adapter进行简单的使用讲解. 这是Adapter的关系图: 下面的所有例子均使用同一个布局 ...

  7. Java模式(适配器型号)

    今天阅读Java该适配器模式,这里有一个小的总结和下谈感受.对于将来使用. 首先.让我们有关适配器先说说. 适应是“来源”至“目标”适应.其中连接这两个的关系是适配器.它负责“源”过度到“目标”. 举 ...

  8. android学习-Adapter适配器进阶

    参考资源 Android 快速开发系列 打造万能的ListView GridView 适配器 实现代码复用,争取打机**的时间. android4.4源码 target=android-19 一般自定 ...

  9. java之类适配器

    类适配器 所谓类适配器,指的是适配器Adapter继承我们的被适配者Adaptee,并实现目标接口Target.由于Java中是单继承,所以这个适配器仅仅只能服务于所继承的被适配者Adaptee.代码 ...

随机推荐

  1. iptables之四表五链

    iptables可谓是SA的看家本领,需要着重掌握.随着云计算的发展和普及,很多云厂商都提供类似安全组产品来修改机器防火墙. iptables概念 iptables只是Linux防火墙的管理工具而已. ...

  2. 开机自启动nginx,php-fpm

    开机自启动nginx,php-fpm(其他服务类似) centos 7以上是用Systemd进行系统初始化的,Systemd 是 Linux 系统中最新的初始化系统(init),它主要的设计目标是克服 ...

  3. Pandas笔记目录

    速查笔记 使用实例 Pandas-数据导入 (未完成) Pandas-数据探索 基础属性 shape indexs columns values dtype/dtypes 汇总和计算描述统计 coun ...

  4. Jenkins发送邮件中文乱码问题解决

    在环境变量中添加: JAVA_TOOL_OPTIONS  =  -Dfile.encoding=UTF8 配置好后,重启Jenkins即可

  5. python updata与深拷贝

    当使用updata更新字典时候 被动更新和主动更新的效果是一样的 意思是说 里面会添加值 而不是保持不变 当将一个字典每次新增到列表时候 要用深拷贝 因为直接append的话 会修改将最新的变量的值同 ...

  6. 年度编程语言最佳候选人:Kotlin vs. C

    转瞬之间,今年已进入为期不足一个月的倒计时模式.在编程语言界,谁将问鼎 2017 年度编程语言?诸多开发者众说纷纭,有人说是最近风头正盛且被纳入中国高考科目的 Python.有人认为还是老牌常青藤 J ...

  7. GO内存管理

    TMalloc模型 http://www.360doc.com/content/16/0811/09/14513665_582407916.shtml http://blog.csdn.net/cho ...

  8. (转)面向对象——UML类图设计

    背景:一直以来,对UMl类图的画法不甚理解,但是随着学习的深入,发现熟练掌握UML类图,能够更好理解代码间的逻辑性,而这也是程序设计的基础所在,所以很有必要把UML好好掌握. UML类图新手入门级介绍 ...

  9. Build CRUD Application with jQuery EasyUI

    http://www.jeasyui.com/tutorial/app/crud.php It has become a common necessily for web application to ...

  10. Java实现POS打印机自定义无驱打印

    Java实现POS打印机自定义无驱打印 热敏打印机使用越来越广泛,而安装驱动相当复杂,万幸的是,几乎所有的热敏打印机都支持ESC/P指令,参考网络上一些资料后,在此整理了一份自定义打印的方案 • 打印 ...