Java中的集合(一)——集合接口
集合的接口与实现分离
Java中的集合遵循接口与实现分离的原则,接口描述集合类要实现的功能,而具体的类则实现(implements)集合接口。同时,Java集合的接口和实现类都是范型的,范型编程最基本(原始)的功能就是用来实现集合的。利用范型,在只编写一套代码的情况下集合可以保存不同类型的对象。
下面研究一个具体的集合类Queue,其接口描述为:
interface Queue<E>
{
void add(Element e);
E remove();
int size();
}
集合类可以有多个不同的实现,Queue可以使用循环数组实现也可以使用链表实现,具体的选择可以根据需求的不同来确定。一种实现为:
class CircualArrayQueue<E> implements Queue<E>
{
//必须实现接口描述中描述的方法
}
在程序中使用集合类时,只需要在构建集合对象时关注不同的集合实现,一旦构建完毕就可以使用集合接口类型引用集合对象。表现为:
Queue<T> queues=new CircualArrayQueue<T>();或者
Queue<T> queues=new LinkedListQueue<T>()
另外在Java API文档中,有一些以Abstract开头的抽象集合类,类似于AbstractQueue,这种抽象集合类主要用于用户想要自己实现集合类时使用。(抽象类与接口的区别对比。)
Java类库中的集合接口和迭代器接口
J ava集合中的基本接口是Collection接口,接口如下:
public interface Collection<E>
{
boolean add(E element);
Iterator<E> iterator();
//还有其他方法
…………
}
add方法用于向集合中添加对象,如果添加成功返回true,否则返回false。如果要插入的对象已经存在,则不会插入对象,集合中不能有重复的对象。Iterator方法返回实现了Iterator接口(迭代器接口)的对象,利用这个对象可以遍历集合中的对象。
迭代器接口描述如下:
public interface Iterator<E>
{
E next();
boolean hasNext();
void remove();
}
集合的迭代器中的next方法可以按照顺序返回集合中的元素,当已经访问到结合结尾时,再调用next()方法会抛出NoSuchElementException异常,因此使用next方法是要先判定hasNext是否为True。
在Java SE 5.0之后,可以使用更简单的方式遍历集合:
for(E element:collection)
{
//do something to element
}
编译器简单的将其翻译成对集合迭代器的操作。要使用这个机制,需要结合对象实现了Iterable接口:
public interface Iterable<E>
{
Iterator<E> iterator();
}
Collection接口扩展了Iterable接口,因此标准库中的任何集合都可以使用这一形式。
需要注意的是,java集合类库中的迭代器与其他迭代器不同,传统的迭代器(例如STL中的迭代器)使用数组索引建模,可以直接利用类似于i++这样的操作使迭代器指向下一个位置,不需要真的移动迭代器。但是java中的迭代器要指向下一个位置必须移动迭代器,使用next操作时候迭代器才会指向下一个位置。这一特性在删除集合中元素是需要注意。例如当需要删除相邻的两个元素时使用:it.remove();it.remove()是错误的。需要先调用next:it.remove();it.next();it.remove()。
因为集合接口都是范型的,因此可以编写操作各种类型的集合元素的方法。Collection接口中除了基本的两个操作外还提供了许多实用的范型方法。要实现Collection接口中的每一个范型方法没有必要,因此java中提供了抽象类AbstractCollection来实现许多的范型方法,但是将size和iterator两个方法抽象化了。这个类实现了Collection接口,然后可以使用各种具体类来继承这个抽象类从而实现具体的集合类。