如果一个程序只包含固定数量的且生命周期都是已知的对象,那么这是一个非常简单的程序。
11.1泛型和类型安全容器
使用泛型可以在编译期防止错误类型放到容器里,使其变成一个编译期错误,而不是运行时错误。
11.2 基本概念
Java容器的用途是保存对象,划分为两个不同的概念
- 1 Collection 一个独立元素的序列,这些元素都服从一条或多条的规则。List必须按照插入的顺序保存元素,而Set不能有重复元素。Queue按照队列规则来确定对象产生的顺序
- 2 Map一组成对的键值对对象,允许你使用键来查找值。ArrayList允许你使用索引来查找值。
11.4 容器的打印
使用Arrays.toString()来产生数组的可打印表示。
11.5 List
LIst接口在Collection的基础上添加大量的方法,是的可以在List的中间插入和移除元素
11.6 迭代器
容器必须有某种方法可以插入元素并在此取回,为了以通用性代码实现这一点,迭代器的概念就可以达到此目的。它的工作是遍历并选择序列中的对象。Java的Iterator只能单向移动,这个Iterator只能用来
- 1) 使用Iterator()要求返回一个Iterator.
- 使用next()获取序列中的下一个元素。
- 3) 使用hasNext()检查序列中是否还有元素
- 4)使用remove()将迭代器元素删除
迭代器统一了对容器的访问方式
ListIterator是一个更加强大的Iterator的子类,它只能用于各种List类的访问。尽管Iterator只能向前移动,但是ListIterator可以双向移动。它还可以产生对于迭代器在列表中指向的当前位置的前一个和后一个元素的索引,并且可以使用set()方法替换它访问过的最后一个元素。你可以通过调用listIterator()方法产生一个指向List开始处的ListIterator,并且可以通过调用listIterator(n)方法创建一个一开始就指向类表索引为n的元素处的ListIterator。
11.7 LinkedList
LinkedList实现基本接口List,在List中间插入和移除时比ArrayList更高效,在随机访问方面要逊色一些。
LinkedList还添加了可以使用其用作栈、队列或双端队列的方法
11.8 Stack
通常指先进后出的容器
LinkList具有能够直接实现栈的所有功能和方法,可以直接将LinkList作为栈使用。
11.9 Set
不保存相同的元素。容易询问某个对象是否在某个Set中,查找成为了Set中最重要的操作。通常会选择HashSet的实现,它对快速查找进行了优化。
Set具有与Collection完全一样的接口,因此没有额外的功能,实际上Set就是Collection,只是行为不同(这是继承与多态思想的典型应用:表现不同的行为)
11.10 Map
Map接口中键和值一一映射. 可以通过键来获取值。
给定一个键和一个值,你可以将该值存储在一个Map对象. 之后,你可以通过键来访问对应的值。
当访问的值不存在的时候,方法就会抛出一个NoSuchElementException异常.
当对象的类型和Map里元素类型不兼容的时候,就会抛出一个 ClassCastException异常。
当在不允许使用Null对象的Map中使用Null对象,会抛出一个NullPointerException 异常。
当尝试修改一个只读的Map时,会抛出一个UnsupportedOperationException异常。
11.11 Queue
队列是一个典型的先进先出的容器。即从容器的一段放入,从另一端取出,放入的顺序和取出的顺序相同。队列被当做一种可靠的将对象从程序的某个区域传输到另一个区域的途径。队列在并发编程中特别重要 因为他们可以安全地将对象从一个容物传输给另一个任务。
LinkedList提供方法支持队列的行为,并且它实现了Queue的接口,因此LinkList可以用作Queue的一种实现。通过将LinkedList向上转型为Queue
11.12 Collection
Collection是描述所有容器共性的根接口,它可能会被认为是一个“附属接口”,即因为要表示其他若干个接口的共性而出现的接口。
11.13 Foreach与迭代器
foreach语法主要用于数组,它可以应用于任何Collection对象。
public class ForEachCollections
public static void main(String[] args){
Collection<String> cs = new LinkedList<String>();
Collection.addAll(cs,"Take the long way home".split(" "));
for(String s : cs){
System.out.print("'"+s+ "'")
}
}
}
//log
'Tage' 'the' 'log' 'way' 'home'
由于cs是一个Collection,所以这段代码展示了能够与foreach一起工作是所有Collection对象的特性。
之所以能够工作,是因为Java SE5引入了新的被称为Iterable的接口,该接口包含一个能够产生Iterator的iterator()方法,并且Iterable接口被foreach用来在序列中移动。因此如果你创建了任何Iterable的类,都可以将它用于foreach语句中。
11.14 总结
Java提供大量的持有对象方式:
- 1 数组讲对象联系起来。容量一旦生成就不能改变。
- 2 Collection保存单一元素,Map保存相关联的键值对。Collection和各种Map都可以在你向其中添加更多元素时,自动调整尺寸。容器不能持有基本类型,但是自动包装机制会仔细的执行基本类型到容器中所持有的包装器类型之间的双向转换。
- 3 像数组一样,List也建立数字索引和对象的关系,数组和List都是排好序的容器。List能够自动扩充容量。
- 4 如果要进行大量的随机访问,就使用ArrayList;如果要经常从表中插入和删除元素,则应该使用LinkedList.
- 5 各种Queue以及栈的行为,由LinkedList提供支持。
- 6 Map是一种将对象(而非数字)与对象相关联的设计,HashMap设计用来快速访问;而TreeMap保持“键”始终处于排序状态,所以没有HashMap快。LinkedHashMap保持元素插入的顺序,但是也通过散列提供快速访问的能力。
- 7 Set不接受重复元素。HashSet提供最快的查询速度,而TreeSet保持元素处于排序状态。LinkListHashSet以插入顺序保持元素。
-
8 新程序中不应该使用过时的Vector、HastTable和Stack
有四种容器:Map、List、Set、Queue,(Queue的Java.util.concurrent实现没有包括这张图)。常用的容器用黑色粗框表示。