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.代码 ...
随机推荐
- js & option keycode
js & option keycode js get option keycode https://keycode.info/ option https://github.com/wesbos ...
- MT【105】待定系数算最大最小
已知$x,y,z>0$,则$max\{2x,\frac{1}{y},y+\frac{1}{x}\}$的最小值______ 分析:首先关注到$2x=\frac{1}{y}=y+\frac{1}{x ...
- 【题解】 Codeforces 662A Gambling Nim (线性基)
662A,戳我戳我 Solution: 我们先取\(ans=a[1] \bigoplus a[2] \bigoplus ... \bigoplus a[n]\),然后我们定义\(c[i]=a[i] \ ...
- C 排序 解题报告
C 排序 题意 给一个\(1\sim n(n\le 10^6)\)排列,求这个排列用冒泡排序从小到大排序的第\(cnt\)步的状态.这里步的定义为,比较一次算一步. 贴个我看的不是很懂的题解,嗯不是很 ...
- 【uoj228】 基础数据结构练习题
http://uoj.ac/problem/228 (题目链接) 题意 给出一个序列,维护区间加法,区间开根,区间求和 Solution 线段树.考虑区间开根怎么做.当区间的最大值与最小值相等时,我们 ...
- 「Vue」vue cli3项目打包为APP方法及坑点
1.执行npm run build之后生成dist文件夹 2.打开HBuilderX新建一个APP项目 3.把dist文件夹里的所有文件拷贝替换到APP文件夹下 4.打开manifest.json文件 ...
- webpack进阶--打包
上一片博文主要让大家了解下究竟webpack是干什么的,明显它是专注于打包的. gulp 和 webpack 的区别 gulp,要求我们一步步写task(es6编译.css压缩.图片压缩.打包. ...
- .net MVC框架里怎么写控件
.net的MVC框架如果选择了Razor引擎就需要自己来写控件了,这里列出了一些简单的控件的书写方法 @*这是TextBox控件的写法*@ @Html.TextBox("textbox1&q ...
- 【跟我学apache-commons】【四】commons-io的使用
commons-io是一款处理io流的工具,封装了很多处理io流和文件的方法,可以大大简化我们处理io流和操作文件的代码.从common-io的官方使用文档可以看出,它主要分为工具类.尾端类.行迭代器 ...
- POJ - 3026 Borg Maze(最小生成树)
https://vjudge.net/problem/POJ-3026 题意 在一个y行 x列的迷宫中,有可行走的通路空格’ ‘,不可行走的墙’#’,还有两种英文字母A和S,现在从S出发,要求用最短的 ...