前言:凡是使用 Java 编程的,几乎肯定会用到集合框架,比如 ArrayList、LinkedList、HashSet、HashMap 等,集合框架的代码绝对是大师级的实现,所以为了更好地使用集合框架,我们有必要系统地学习下集合框架的内容。
一、接口综述
集合框架的整体结构图如下(摘自《Thinking In Java》):
上图也许有些复杂,因为包含了很多我们很少用到的抽象类,其实,只需要记住下面两张图即可(摘自张龙的 collection 集合教程):
Collection 接口里定义了如下操作集合元素的方法:
- boolean add(Object o):用于向集合里添加一个元素,如果集合对象被添加操作确实改变了,则返回 true。
- boolean addAll(Collection c):把集合 c 里的所有元素添加到指定集合里,如果集合对象被添加操作改变了,则返回 true。
- void clear():清除集合里的所有元素,将集合长度变为 0.
- boolean contain(Object o):判断集合里是否包含指定元素,包含则返回 true。
- boolean containAll(Collection c):判断集合里是否包含集合 c 里的所有元素。
- boolean isEmpty():判断集合是否为空,当集合长度为 0 时返回 true。
- Iterator iterator():返回一个 Iterator 对象,用于遍历集合里的元素。
- boolean remove(Object o):删除集合中指定的元素 o,当集合里包含了一个或多个元素 o 时,这些元素将被删除,该方法返回 true。
- boolean removeAll(Collection c):从集合中删除集合 c 里面包含的所有元素,如果删除了一个或多个元素,则返回 true。
- boolean retainAll(Collection c):从集合中删除集合 c 里不包含的元素,如果删除了一个或多个元素,则返回 true。
- int size():该方法返回集合里的元素的个数
- Object[] toArray():该方法把集合转换成一个数组,所有的集合元素变成对应的数组元素。
Iterator 接口也是 Java 集合框架的成员,但它与 Collection 系列、Map 系列的集合不一样:Collection 系列集合、Map 系列集合主要用于盛装其他对象,而 Iterator 则主要用于遍历(即迭代访问)Collection 集合中的元素,Iterator 对象也被称为迭代器。
Iterator 接口包含 3 个方法:
public interface Iterator<E>{ E next(); // 返回集合里的下一个元素 boolean hasNext(); // 如果被迭代的集合元素还没有被遍历,则返回 true void remove(); // 删除集合里上一次 next 方法返回的元素 }
通过反复调用 next 方法,可以逐个访问集合中的每个元素。但是,如果到达了集合的末尾,next 方法将抛出一个 NoSuchElementException。因此,需要在调用 next 之前调用 hasNext 方法。如果迭代器对象还有多个供访问的元素,则返回 true。如果想要查看集合中的所有元素,就请求一个迭代器,并在 hasNext 返回 true 时反复地调用 next 方法。例如:
Collection<String> c = ...; Iterator<String> iter = c.iterator(); while (iter.hasNext()) { String element = iter.next(); do something element }
不过,从 Java SE 5.0 起,这个循环可以采用一种更加优雅的缩写方式。用 "for each" 循环可以更加简练地表达同样的循环操作:
for (String element : c) { do something else }
PS:编程老手会注意到:Iterator 接口的 next 和 hasNext 方法与 Enumeration 接口的 nextElement 和 hasElement 方法的作用一样,但是可能是 Java 集合类库的设计者觉得这个方法名太长,于是引入了具有较短方法的新接口。
注意:这里还有个有用的类推。可以将 Iterator.next 与 InputStream.read 看作为等效的。从数据流中读取一个字节,就会自动地 "消耗掉" 这个字节。下一个调用 read 将会消耗并返回输入的下一个字节,用同样的方式,反复地调用 next 就可以读取集合中所有元素。
Iterator 接口的 remove 方法要和 next 方法一起使用,如果调用 remove 之前没有调用 next 是不合法的,会抛出一个 IllegalStateException 异常。
如果想删除相邻的两个元素,需要这样:
it.next(); it.remove(); it.next(); it.remove();
将接口是空洞的,因为没有具体的精彩的实现,所有接下来还是具体介绍 集合框架中的几个常用的实现类: