# 自定义集合
一般中使用前面提供的就够用了,也许你需要自定义自己的 Collection 实现类。在 Java 平台提供的抽象实现的帮助下,这是相当容易的。
# 编写实现的原因
下面列表显示了自定 Collection 的实现原因:
持久性
内置的实现类都是驻留在内存中。你可以构建一个数据库来实现 持久化在数据库中,这样的集合可以由多个程序同时访问。
特定的应用
这是一个非常广泛的类别。比如 对 map 的操作进行事件的监测,get 操作时,发起回调事件等
高性能,特殊用途
很多数据结构采取限制使用的方式,比通用实现提供更好的性能。
增强功能
比如让 hashMap 支持重复的元素
方便
你可能需要额外的实现,提供超越 Java 平台所提供的便利。
适配器
假设你使用的是传统的 API,它有自己的特有的 api。你可以编写一个运行这些集合在 Java 集合框架中操作的适配器实现。
# 如何编写自定义实现
public class MyList<T> extends AbstractList<T> {
private final T[] a;
public MyList(T[] a) {
this.a = a;
}
@Override
public T get(int index) {
return a[index];
}
@Override
public int size() {
return a.length;
}
//模仿java.util.Arrays 中的功能
public static <T> List<T> asList(T[] a) {
return new MyList<>(a);
}
public static void main(String[] args) {
List<String> list = MyList.asList(new String[]{"1","2","3"});
System.out.println(list);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
继承 AbstractList
,并实现 get
,size
方法,就得到了 ListIterator,批量操作,搜索操作,哈希代码计算,比较和字符串表示的 toString
以下列表中间了抽象实现:
- AbstractCollection:一个 Collection 既不是 Set 也不是 List。至少,你必须提供 iterator 和 size 方法。
- AbstractSet:一个 Set; 利用相同 AbstractCollection。
- AbstractList:一个 List 由一个随机存取数据存储备份,如数组。至少必须提供 positional access 的方法(get 和任选 set,remove 和 add)和 size 方法。抽象类需要照顾 listIterator(和 iterator)。
- AbstractSequentialList:一个 List 通过顺序存取数据存储备份,诸如链表。至少,你必须提供 listIterator 与 size 方法。抽象类负责位置访问方法。(这是相反的 AbstractList。)
- AbstractQueue:至少,你必须提供的 offer,peek,poll,和 size 方法以及 iterator 支持 remove。
- AbstractMap:一个 Map。至少,你必须提供 entrySet 视图。这通常是与实现 AbstractSet 类。如果 Map 是修改的,你还必须提供 put 方法。
# 编写自定义实现的过程如下
- 从上面的列表中选择适当的抽象实现类
- 为类的抽象方法提供实现。如果你的自定义集合是可修改的,你不得不重写一个或多个具体的方法。抽象实现类的 API 文档会告诉你需要覆盖哪些方法。
- 测试,调试实现。
- 如果你关注性能。请阅读你继承抽象实现类的 API 文档,然后重写实现,请务必衡量重写前后的性能比较。一般此步骤最好省略