11.1 泛型和类型安全的容器
通过使用泛型,可以在编译期内防止错误类型的对象放置到容器中。
Java SE5 之前编译器允许向容器中插入不正确的类型对象。
使用Java泛型来创建类对象十分复杂,但通过应用预定义的泛型通常十分简单。
例如保存Apple对象的ArrayList容器,声明ArrayList<Apple>
,尖括号内可以是多个类型参数,指定了容器实例可以保存的对象的类型。
11.2 基本类型
Java 容器的两个不同概念的划分
1. Collection 独立元素的序列,List ,Set,Queue
2. Map 一组成对的键值对 对象,允许通过键值来查找值。类似于关联数组和字典
11.3 添加一组元素
Arrays.asList()
转换的List,其底层表示是数组,因此不能调整尺寸。当有引发数组尺寸改变的操作时,可能会引发Unsupported Operation
错误 ;
在collection中添加一组元素可以使用Arrays和Collections类的方法。
1. Arrays.asList();
方法将接受一个数组或是一个用逗号分割的可变长元素列表并将其转换为List对象
2. Collections.addAll()
方法将接受一个collection对象,以及用逗号分割的可变长元素列表,将元素添加到collection中
Arrays.asList()注意点
- 该方法不适用于基本数据类型(byte,short,int,long,float,double,boolean)
- 该方法将数组与列表链接起来,当更新其中之一时,另一个自动更新
11.4 容器的打印
直接打印容器的显示样子
上图显示了两种容器类型划分。Collection在每个槽只能保存一个元素。此容器包括: List、Set、Queue。。Map在槽中每次保留两个对象,即键值与之相关联的值。
11.5 List
List : 将元素维护在特定的序列中。 List接口在Collection的基础上添加大量的方法,使得可以在List中插入和移除元素。
有两种类型的List:
1. 基本的ArrayList : 它长于随机访问元素,但是在ArrayList中插入和移除元素时比较慢.
2. LinkedList : 它在List中进行插入和删除的代价较小,提供了优化的顺序访问。虽然LinkedList在随机访问的性能上较慢,但是它的特性较ArrayList更大。
List 的基本方法:
1. contains : 查看对象是否在列表中
2. remove : 从列表中删除一个对象
3. indexOf : 获取对象所在的序号
上述三种方法都需要 使用对象的equals(),来找出列表中的对象。*所以必须注意List的行为会随着equals的行为变化而变化
- subList : 从较大的列表中创建出一个片段来,sublist的基础是原始列表,所以对片段列表的所有修改都会反映到原始列表中
- containsAll : 验证列表中是否包含一些列的对象。
- Collections.sort Collections.shuffle : 排序和打乱
- retainAll : 交集操作
- removeAll : 差集操作
- set : === replace 替换某个位置的元素
- isEmpty : 空检验
- clear : 清空
- addAll : 添加全部的元素 === Collection.addAll();
- toArray : 将任意的collection转换为数组
11.6 迭代器
迭代器设计模式 : 遍历并选择序列中的对象,而客户端程序员不必知道或者关心序列底层的结构。
Java 的Iterator 只能单项移动,这个Iterator只能用来
1. 使用方法iterator() 要求容器返回一个Iterator。Iterator将准备好返回序列的第一个元素
2. 使用next() 方法获取序列中的下一个元素
3. 使用hasNext() 检查序列中是否还有准备好返回的序列
4. 使用remove() 将迭代器最新返回的元素删除。
ListIterator
ListIterator是一个更加强大的Iterator的子类型,它只能用于各种List类的访问。尽管Iterator只支持向前移动,但是ListIterator支持双向访问。listIterator(n)
获得一个一开始就指列表索引指向n的元素处的ListIterator。
11.7 LinkedList
实现了基本的List接口,但他执行插入删除操作较ArrayList更为高效,然而在随机访问的性能较为逊色。LinkedList 添加了可以使其作为栈,队列,双端队列的方法
11.8 Stack
LIFO 容器 有时候栈也被称为叠加栈。
LinkedList 具有实现栈的所有功能的方法,所以可以将LinkedList直接作为栈使用。
11.9 Set
Set容器重点为: 快速查找的优化,和判断相同元素
归属性: 检查某一个对象是否存在某一个Set中
Set是基于对象的值来确定归属性的。
HashSet : 使用了散列函数
TreeSet : 将元素存储在红-黑树的数据结构中
LinkedHashSet : 使用链表来维护插入顺序
11.10 Map
Map 具有将对象映射到其他对象的能力。容器中最好不要使用基本类型
Map 与其他容器一致可以简单地扩展到多维。
Map 可以返回其键值的Set集合,Collection集合。 KeySet()
方法。使用 keyset ,可以迭代遍历Map。
Queue
队列是一个 (FIFO) 先进先出容器。 LinkedList提供了方法支持队列的行为,并且它实现了Queue接口,因此LinkedList可以作为Queue的一种实现。
常用方法
1. offer : 将一个元素插到队尾
2. peek \ element : 返回对头,peek 可以返回null element 抛出NoSuchElementException
3. poll \ remove : 移除对头 poll可以返回 null remove 抛出 NoSuchElementException
11.11.1 优先队列 PriorityQueue
在插入元素的时候,这个对象会在队列中被排序。默认的排序是对象在队列的自然顺序,可以通过Comparator来修改排序规则。PriorityQueue 可以保证当你调用 peek() poll() remove() 方法的时候,获取的元素优先级别最高。
11.12 Collection 和 Iterator
Collection : 描述所有序列容器共性的根接口,他可能会被认为是一个“附属接口”
11.14 总结
- 数组可以将数字和对象联系起来,它保存类型明确的对象,在查询对象的时候不需要对结果进行类型转换,它可以使多维的,可以保存基本数据类型(boolean byte char short int long flout double )。 但是一旦数组生成,其容量就不能再改变。
- Collecton保存单一元素,而Map保存相关联的键值对。有了java的泛型,可以指定容器所放的对象类型,并且在取出对象后不必进行类型转换。 容器不支持基本类型,但是自动包装技术会仔细地保存基本类型到容器中。
- 像数组一样,List也建立数字索引与对象的关联,因此,数组和List都是可以排序的。List可以自动扩充容量
- 如果要进行大量的随机访问,就是用ArrayList,如果要经常从表中插入或删除元素,则应该使用LinkedList
- 各种Queue以及栈的行为是由LinkedList提供的
- Map是对象和对象建立关联设计。HashMap用来快速访问,TreeMap保持了键值排序状态,LinkedHashMap两者兼顾
- set不接受重复元素。HashSet提供最快的查询速度,TreeSet保持了元素始终处于排序状态,LinkedHashSet以插入顺序保存元素。
- 新程序中不应该使用过时的Vector HashTable Stack