java adapter(适配器)惯用方法
如果现在有一个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(适配器)惯用方法的更多相关文章
- Android中ListView 控件与 Adapter 适配器如何使用?
一个android应用的成功与否,其界面设计至关重要.为了更好的进行android ui设计,我们常常需要借助一些控件和适配器.今天小编在android培训网站上搜罗了一些有关ListView 控件与 ...
- GoldenGate for Java Adapter介绍一(原理篇)
前言 Oracle Goldengate在很早前就推出了一个for java的版本,主要目的是方便把关系型数据实时写入到不支持的目标端,如JMS或Redis等key value数据库.在Hadoop刚 ...
- java演示适配器(adapter)模式
为什么要使用模式: 模式是一种做事的一种方法,也即实现某个目标的途径,或者技术. adapter模式的宗旨就是,保留现有类所提供的服务,向客户提供接口,以满足客户的需求. 类适配器:客户端定义了接口并 ...
- Java 实现适配器(Adapter)模式
平时我们会常常碰到这种情况,有了两个现成的类,它们之间没有什么联系.可是我们如今既想用当中一个类的方法.同一时候也想用另外一个类的方法.有一个解决方法是.改动它们各自的接口.可是这是我们最不愿意看到的 ...
- Android adapter适配器的学习
学习Android有一点时间,说说自己的学习感悟. 首先呢,先说说适配器的作用,顾名思义,它就是把数据定义好一定的规则,使得我们可以用到ListView GridView等上面 所以说这玩意,还是得好 ...
- Android adapter适配器的使用
说起Adapter的使用,首先想到的就是listview或各种各样的Adapter.下面我们对常用的一些Adapter进行简单的使用讲解. 这是Adapter的关系图: 下面的所有例子均使用同一个布局 ...
- Java模式(适配器型号)
今天阅读Java该适配器模式,这里有一个小的总结和下谈感受.对于将来使用. 首先.让我们有关适配器先说说. 适应是“来源”至“目标”适应.其中连接这两个的关系是适配器.它负责“源”过度到“目标”. 举 ...
- android学习-Adapter适配器进阶
参考资源 Android 快速开发系列 打造万能的ListView GridView 适配器 实现代码复用,争取打机**的时间. android4.4源码 target=android-19 一般自定 ...
- java之类适配器
类适配器 所谓类适配器,指的是适配器Adapter继承我们的被适配者Adaptee,并实现目标接口Target.由于Java中是单继承,所以这个适配器仅仅只能服务于所继承的被适配者Adaptee.代码 ...
随机推荐
- download & excel & blob
download & excel & blob Blob https://developer.mozilla.org/en-US/docs/Web/API/Blob FileReade ...
- 模拟APP存储空间、内存不足情况下软件正常运行
1.进行临界测试,手机盘空间存满的条件下应用会有何表现: 方法一:adb shell dd if=/dev/zero of=/mnt/sdcard/bigfile 方法二:哆啦A工具生成文件 2.内存 ...
- BZOJ 4361 isn | DP 树状数组
链接 BZOJ 4361 题面 给出一个长度为n的序列A(A1,A2...AN).如果序列A不是非降的,你必须从中删去一个数, 这一操作,直到A非降为止.求有多少种不同的操作方案,答案模10^9+7. ...
- 四、spring boot 1.5.4 日志管理
spring boot日志默认采用logback进行输出,你可以对logback进行定制化,方法如下: 在resources文件夹下建立logback.xml配置文件 <?xml version ...
- myeclipse和maven的clean和build
转: 详解myeclipse和maven的clean和build 2018年04月20日 11:33:34 群星坠 阅读数:3529 版权声明:本文为博主原创文章,未经博主允许不得转载. http ...
- String.format VS. StrSubstitutor VS. NamedParameterJdbcTemplate
在Java中,想要用一个字符串模块根据参数的不同来产生不同的字符串,主要有以下两种办法: Java String.format() 在JDK1.5中,String类新增了一个很有用的静态方法Strin ...
- centos7下设置opencv环境变量
最近要装YOLO,但是MAKE的时候总是找不到OPENCV的路径, 原因是:我以前卸载过一次OPENCV,然后自己重新安装了opencv2.4.10, 因为当时只在QT 中用,所以编译完也没有设置环 ...
- 「Django」contenttypes基本用法
当一张表和多个表ForeignKey关联,并且多个FK中只能选择其中一个或其中n个时,可以利用contenttypes,只需定义三个字段就搞定! contenttypes 是Django内置的一个应用 ...
- faster rcnn 详解
转自:https://zhuanlan.zhihu.com/p/31426458 经过R-CNN和Fast RCNN的积淀,Ross B. Girshick在2016年提出了新的Faster RCNN ...
- python---django中orm的使用(4)字段,参数(on_delete重点)补充,一对多,一对一,多对多
1.索引: 普通索引:加快查找速度 唯一索引:加快查找速度,唯一约束 主键索引:加快查找速度,唯一索引,不为空 class UserInfo(models.Model): username = mod ...