- 泛型和类型安全的容器
- 使用Java SE5之前,编译器允许向容器中插入不正确的类型,Java SE5引入泛型之后,应用预定义的泛型可以在编译期防止将错误类型的对象放到容器中。
- 基本概念
- Collection。一个独立元素的序列,这些元素都服从一条或多条规则。List必须按照插入顺序保存元素,Set不能保存重复元素,Queue按照排队规则来确定对象产生的顺序(通常与他们插入的顺序相同)。
- Map。一组成对的“键值对”对象,允许使用键来查找值。其中键不能重复,否则键对应的值会被覆盖。
- HashMap——提供了最快的查找技术,也没有按照任何明显的顺序来保存元素;
- TreeMap——按照比较结果的升序来保存键;
- LinkedHashMap——按照插入顺序保存键,同时还保留了HashMap的查询速度。
- List。List可以将元素维护在特定的序列中。List包含两个子类:ArrayList和LinkedList。
- ArrayList——随机访问较快,但是在中间插入和移除元素较慢;
- LinkedList——随机访问较慢,但是在List中间插入和移除元素较快,同时提供了优化的顺序访问机制。LinkedList还添加了可使其用作栈、队列和双端队列的方法。
- Set。Set不保存重复元素。Set中最长被使用的是测试归属性,因此查找成了Set中最重要的操作。Set具有与Collection完全一样的接口。
- HashSet——使用了散列,所以HashSet具有较快的查找速度;
- TreeSet——将元素存储在红-黑树数据结构中,保持一定的顺序;
- LinkedHashSet——也使用了散列,同时使用了链表来维护元素的插入顺序。
- 迭代器——Iterator(只能单向移动)迭代器能够将遍历序列的操作与序列底层的结构分离;迭代器统一了对容器的访问方式。
- 使用方法iterator()要求容器返回一个Iterator;
- 使用next()获取序列中的下一个元素;
- 使用hasNext()检查序列中是否还有元素;
- 使用remove()将迭代器新近返回的元素删除。
- ListIterator——只能用于各种List类的访问
- ListIterator可以双向移动;
- 它可以产生相对于迭代器在列表中指向的当前位置的前一个和后一个元素的索引,并且可以使用set()方法替换它访问过的最后一个元素;
- 通过listIterator()可以产生一个指向List开始处的ListIterator;
- 通过listIterator(n)可以产生一个指向List列表索引为n的元素处的ListIterator。
- Stack——“栈”通常是指“后进先出”(LIFO)的容器
- 由于LInkedList具有能够直接实现栈的所有功能的方法,因此可以直接将LinkedList作为栈使用。
- 但是如果只是想使用栈的功能,最好能组合LinkedList实现而不是继承或直接用LinkedList代替,避免引入LinkedList的其他方法(Java1.0设计就犯了这个错误)
public class Stack<T> {
private LinkedList<T> storage = new LinkedList<T>();
public void push(T v) { storage.addFirst(v); }
public T peek() { return storage.getFirst(); }
public T pop() { return storage.removeFirst(); }
public boolean empty() { return storage.isEmpty(); }
public String toString() { return storage.toString(); }
}
- Queue——队列是一个典型的先进先出(FIFO)的容器(队列在并发编程中特别重要)。
- LinkedList提供了方法支持队列的行为,并且实现了Queue接口,因此是Queue的一种实现;
- offer():在队尾插入元素;
- peek()和element()都将在不移除的情况下返回队头;
- poll()和remove()方法将移除并返回队头;
- 区别在于当队列为空时,peek()和poll()返回null,而element()和removed()会抛出NoSuchElementException异常。
- PriorityQueue——可排序队列
- PriorityQueue默认的排序将使用对象在队列中的自然顺序,但你可以通过提供自己的Comparator来修改顺序。
- Collection和Iterator(略)
- Foreach与迭代器
- foreach语法主要用于数组,但也可以应用于任何Collection对象。之所以如此,是因为Java SE5引入了Iterable接口,该接口包含一个iterator()方法能产生Iterator对象,并且Iterable接口被foreach用来在序列中移动,因此你创建任何实现Iterable的类,都可以使用foreach语句。