Java编程思想(第四版)中的容器类图:
类图中以Abstract开头的为抽象类。从容器类图中可以发现,数据容器主要分为了两类,即Collection接口和Map接口,其中,Collection接口用于存放独立元素的序列。Map接口用于存放key-value型的元素对。
1. Collection
Collection包含List、Set、Queue(为SE5新增)。Collection接口中定义的方法如下(不含从Object继承来的方法):
方法 | 描述 |
public boolean add(E e) | 向集合中增加元素 |
public boolean addAll(Collection<? Extends E>c) | 向集合中加入一组数据,泛型指定了操作上限 |
public void clear() | 清空所有的内容 |
public boolean contains(Object o) | 判断是否有指定的内容查找 |
public boolean containsAll(Collection<?> c) | 查找一组数据是否存在 |
public boolean isEmpty() | 判断集合的内容是否为空 |
public iterator()<E>interator() | interator接口实例化 迭代输出 |
public boolean remove(Object o) | 从集合中删除指定的对象 |
boolean removeAll(Collection<?> c) | 从集合中删除一组对象 |
public int size() | 取得集合的长度 |
public Object[] toArray() | 取得全部的内容,以数组的形式返回 |
public<T>[] toArray(T[] a ) | 取得全部内容返回一个数组,返回结果的运行时类型与参数数组a的类型相同,而不是单纯的Object |
容器类对象在调用remove、contains等方法时需要比较对象是否相等,这会涉及到对象类型的equals方法和hashCode方法;对于自定义的类型,需要重写equals方法和hashCode方法以实现自定义对象相等规则。
注意:Collection没有get()方法来取得某个元素。只能通过iterator()遍历元素。Set和collection一样。而List可以通过get()方法来一次取出一个元素
List
List相对于Collection新增方法有:
方法 | 描述 |
public void add(int index, E element) | 在指定的位置处加入一个元素 |
public boolean addAll(Collection<? extends E> c) | 普通 在指定的位置加入一组元素 |
public E get(int index) | 通过索引位置取出某个元素 |
public E remove(int index) | 删除指定位置的内容 |
public E set(int index, E element) | 修改指定位置的内容 |
public ListIterator<E> listIterator() | 为ListIterator接口实例化 |
public List<E> subList(int fromIndex, int toIndex) | 截取自集合 |
常用到的为ArrayList和LinkedList。其区别在于:
1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
当操作是在一列数据的后面添加数据而不是在前面或中间,并且需要随机地访问其中的元素时,使用ArrayList会提供比较好的性能;当你的操作是在一列数据的前面或中间添加或删除数据,并且按照顺序访问其中的元素时,就应该使用LinkedList了。
类Java.util.collections提供了一些List的常用算法,如下:
void sort(List l); 排序
void shuffle(List l); 对List内对象随机排列,打乱顺序
void reverse(List l); 对List内对象逆序排列
void fill(Lsit,Object) 用Object重写整个List容器
void copy(List dest,List src); 拷贝
int binarysearch(List,Object); 对有序List进行二分查找
注意:java.util.Collection 是一个集合接口。它提供了对集合对象进行基本操作的通用接口。java.util.Collections 是一个包装类。它包含有各种有关集合操作的静态多态方法,此类不能实例化。应用Collections.sort(List)。
Set
Set接口是Collection的子接口,Set接口没有提供的额外方法,但实现Set接口的容器类中的元素是没有顺序的,而且不可以重复,Set接口可以与数学中”集合“的概念相对应。Set的实现有HashSet、TreeSet和LinkedHashSet等,一般选择HashSet。
HashSet 是为快速查找设计的Set,存入 HashSet的元素必须定义HashCode()方法。
TreeSet 保持次序的Set,底层为树结构。使用它可以从Set中提取有序的序列。元素必须实现Comparable接口。只能添加同类型的数据。每添加一个都进行一次排序,实现了SortedSet接口。
LinkedHashSet 具有HashSet的查询速度,且内部使用链表维护元素的顺序(此处顺序指插入的次序)。在使用迭代器遍历Set时会按元素插入次序显示。元素也需定义HashSet方法。
Queue
Queue接口与List、Set同一级别,都是继承了Collection接口。LinkedList实现了Queue接口。Queue接口窄化了对LinkedList的方法的访问权限(即在方法中的参数类型如果是Queue时,就完全只能访问Queue接口所定义的方法 了,而不能直接访问 LinkedList的非Queue的方法),以使得只有恰当的方法才可以使用。BlockingQueue 继承了Queue接口。
Queue多用于并发操作中。如果你试图向一个 已经满了的阻塞队列中添加一个元素或者是从一个空的阻塞队列中移除一个元索,将导致线程阻塞.在多线程进行合作时,阻塞队列是很有用的工具。工作者线程可 以定期地把中间结果存到阻塞队列中而其他工作者线线程把中间结果取出并在将来修改它们。队列会自动平衡负载。如果第一个线程集运行得比第二个慢,则第二个 线程集在等待结果时就会阻塞。如果第一个线程集运行得快,那么它将等待第二个线程集赶上来。
Iterator
简单说:Iterator就是一个统一的遍历我们集合中所有元素的方法:
1、所有实现了Collection接口的容器类都有一个iterator方法用以返回一个实现了Iterator接口的对象。
2、Iterator对象称作迭代器,用以方便的实现对容器元素的遍历实现。
3、Iterator实现了下列方法:
boolean hasNext();
Object next();
void remove(); //从迭代器指向的 collection 中移除迭代器返回的最后一个元素(即游标左面的元素)。每次调用 next 只能调用一次此方法。如果进行迭代时用调用此方法之外的其他方式修改了该迭代器所指向的 collection,则迭代器的行为是不确定的。
Iterator一般使用方法:
Iterator iterator = collection.iterator();
while(iterator.hasNext()){
//next()的返回值类型是Object类型,需要转换为相应类型
T t= (T)iterator.next();
}
2. Map
Map接口定义了存储“键(key)---值(value)映射对”的方法。Map主要用于存储健值对,根据键得到值,因此不允许键重复(重复了覆盖了),但允许值重复。Map接口定义的方法如下:
更新方法:
clear() | 从 Map 中删除所有映射 |
remove(Object key) | 从 Map 中删除键和关联的值 |
put(Object key, Object value) | 将指定值与指定键相关联 |
putAll(Map t) | 将指定 Map 中的所有映射复制到此 map |
返回方法
entrySet() | 返回 Map 中所包含映射的 Set 视图。 Set 中的每个元素都是一个 Map.Entry 对象,可以使用 getKey() 和 getValue() 方法 (还有一个 setValue() 方法)访问后者的键元素和值元素 |
keySet() | 返回 Map 中所包含键的 Set 视图。 删除 Set 中的元素还将删除 Map 中相应的映射(键和值) |
values() | 返回 map 中所包含值的 Collection 视图。 删除 Collection 中的元素还将删除 Map 中相应的映射(键和值) |
访问和测试方法:
get(Object key) | 返回与指定键关联的值 |
containsKey(Object key) | 如果 Map 包含指定键的映射,则返回 true |
containsValue(Object value) | 如果此 Map 将一个或多个键映射到指定值,则返回 true |
isEmpty() | 如果 Map 不包含键-值映射,则返回 true |
size() | 返回 Map 中的键-值映射的数目 |
Map接口的实现由HashMap、TreeMap、LinkedHashMap、WeakHashMap、ConcurrentHashMap、IdentityHashMap。
Hashmap 是一个最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度,遍历时,取得数据的顺序是完全随机的。HashMap最多只允许一条记录的键为Null;允许多条记录的值为 Null;HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap;可能会导致数据的不一致。如果需要同步,可以用 Collections的synchronizedMap方法使HashMap具有同步的能力,或者使用ConcurrentHashMap。
LinkedHashMap保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.也可以在构造时用带参数,按照应用次数排序,可采用最近最少使用(LRU)算法。在遍历的时候会比HashMap慢,不过有种情况例外,当HashMap容量很大,实际数据较少时,遍历起来可能会比LinkedHashMap慢,因为LinkedHashMap的遍历速度只和实际数据有关,和容量无关,而HashMap的遍历速度和他的容量有关。
TreeMap实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。
WeakHashMap以弱键 实现的基于哈希表的 Map。在 WeakHashMap 中,当某个键不再正常使用时,将自动移除其条目。更精确地说,对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的丢弃,这就使该键成为可终止的,被终止,然后被回收。丢弃某个键时,其条目从映射中有效地移除。