容器总结
Java提供了大量持有对象的方式:
- 数组将数字与对象联系起来。它保存类型明确的对象,查询对象时,不需要对结果做类型转换。它可以是多维的,可以保存基本类型的数据。但是,数组一旦生成,其容量就不能改变。
- Collection保存单一的元素,而Map保存相关联的键值对。有了Java的泛型,你就可以指定容器中存放的对象类型,因此你就不会将错误类型的对象放置到容器中,并且在从容器中获取元素时,不必进行类型转换。各种Colection和各种Map都可以在你向其中添加更多的元素时,自动调整其尺寸。容器不能持有基本类型,但是自动包装机制会仔细地执行基本类型到容器中所持有的包装器类型之间的双向转换。
- 像数组一样,List也建立数字索引与对象的关联,因此,数组和List都是排好序的容器。List能够自动扩充容量。
- 如果要进行大量的随机访问,就使用ArrayList,如果要经常从表中间插入或删除元素,则应该使用LinkedList。
- 各种Queue以及栈的行为,由LinkedList提供支持。
- Map是一种将对象(而非数字)与对象相关联的设计。HashMap设计用来快速访问;而TreeMap保持“键”始终处于排序状态,所以没有HashMap快。LinkedHashMap保持元素插入的顺序,但是也通过散列提供了快速访问能力。
- Set不接受重复元素。HashSet提供最快的查询速度,而TreeSet保持元素处于排序状态。LinkedHashSet以插入顺序保存元素。
- 新程序中不应该使用过时的Vector、Hashtable和Stack。
你可以看到,其实只有四种容器:Map、List、Set和Queue,它们各有两到三个实现版本(Queue的java.util.concurrent实现没有包括在上面这张图中)。常用的容器用黑色粗线框表示。
点线框表示接口,实线框表示普通的(具体的)类。带有空心箭头的点线表示一个特定的类实现了一个接口,实心箭头表示某个类可以生成箭头所指向类的对象。例如,任意的Collection可以生成Iterator,而List可以生成ListIterator(也能生成普通的Iterator,因为List继承自Collection)。 下面的示例展示了各种不同的类在方法上的差异。实际的代码来自第15章,我在这里只是调用它以产生输出。程序的输出也展示了在每个类或接口中所实现的接口:
除了TreeSet之外的所有Set都拥有与Collection完全一样的接口。List和Collection存在着明显的不同,尽管List所要求的方法都在Collection中。另一方面,在Queue接口中的方法都是独立的,在创建具有Queue功能的实现时,不需要使用Collection方法。最后,Map和Collection之间的唯一重叠就是Map可以使用entrySet()和values()方法来产生Collection。