首先看一张<Thinking in Java>中的图
Java中的集合主要包括两大类, 一类是 Collection 另一类是 Map , 这样分类的原因很简单 Map 和 其他集合保存数据的方式有着本质的不同.下面也主要从这两大类介绍java中的集合.
Collection
List接口:
- ArrayList是其一个实现子类, 正如其名字一样,一个像数组一样的容器,你可以简单的把它当做一个可以自动扩容的数组来使用,其特点是随机访问的效率较高.
- LinkList 采用链表来维护内部的数据,其特点是随机插入和删除的效率较高, 在List中间插入元素是可行的,如果你需要经常这么做,应该考虑使用 LinkList.
- List 按照添加元素的顺序来维护自身的数据.
- List 的很多行为都是依赖于 equals 方法,如 retainAll, removeAll.
Set接口:
- HashSet 是一个速度最快的实现子类,因为它不会去考虑你加入元素的相关顺序,采用的是一种比较复杂的散列算法来保存数据.
- TreeSet(实现了 SortSet 接口) 可以按照比较结果的升序方式 (自然排序---comparable接口) 保存对象,因为考虑了顺序的原因,获取元素的速度慢于 HashSet.
- LinkedHashSet 可以按照添加的顺序保存对象,同时拥有和 HashSet 相同的查询速度.
- Set不能保存重复元素,实现不重复的关键性因素在于 hashCode 和 equals
- 如果我们把没有覆写 hasCode 和 equals 方法的类型用于 Set , 将会产生很大的麻烦( 即使这在运行时并不会错误 ), 这会导致违背了 Set 不含有重复值的契约, 因为Object 对象的 hasCode 和 equals 方法默认都是基于对象的内存地址的比较和操作.
Queue接口:
- LinkedList 提供方法实现队列的行为, 它实现了 Queue 接口,<Thinking in java> 中说到, Queue在并发编程中特别重要,因为它可以安全的将对象从一个任务传输到另外一个任务.
- ArrayDqueue(实现了Dqueue接口), 一个更高效实现栈和队列的方式,尽管它是一个双向队列, Java的官方描述为:
This class is likely to be faster than Stack when used as a stack, and faster than LinkedList when used as a queue.
LinkedList 提供实现 队列 行为的方法有
- offer 插入一个元素到队尾.
- peek 和 element 在不移除队头元素的情况下返回队头元素. peek 方法在队列为空时返回 null ,而 element会抛出异常.
- pool 和 remove 方法移除并且返回队头元素,区别同上.
LinkedList 同样可以实现 栈
Map
Map 的实现子类和 Set 很类似,主要有如下几个:
- HashMap 同 HashSet 一样,也是获取元素速度最快的实习子类, <Thinking in Java> 中说到: HashMap 要成为你默认选择,在你不需要考虑其他特性的情况下,因为它对速度进行了优化.
- TreeMap 可以按照 键 的比较结果升序保存键.
- LinkedHashMap 按照添加元素的顺序保存键,并且还拥有保留了HashMap的查询速度, 在它的构造方法中, 可以指定是否采用 最近最少(LRU)算法, 如果采用, 那么最近被访问过的元素总是会被移动到最后端.
- Map 对 Key 的区分同样是采用的 hasCode 方法和 equals 方法, 因此如果我们要把自定义类型作为 Map 的键, 应该同时覆写 equals 和 hasCode 方法.
Map.Entry 接口:
- 该接口是Map的一个内部接口, 我们都知道, Map 是用 键-值 来实现的数据结构,那么这些 键-值 在 Map 内部是如何维护的呢? 就是通过这个接口.
- 感兴趣的同学可以去 Map 的源码中看看, 你会发现 Map 内部会存在一个 Entry(在某些实现中可能是Node) 对象数组, 而这个 Entry(Node) 对象便是实现了 Map.Entry 接口的对象, 这个接口定义了这么几个方法: getKey() , getValue() , setValue()
- Map 在内部就是把一个一个的 键-值 对封装到一个 Entry 对象中(其实就是一个JavaBean), 方便后期对这些对象的操作, 然后在不同的 Map 的实现子类中按照不同的特性和需求把这些 Entry 对象按照不同的数据结构进行组织和排列.
- 如 HashMap 是用的数组和链表结合(取二者的优点,所以HashMap速度最快,当然这还有散列机制的功劳), TreeMap 是按照 二叉树的方式排列, LinkedHasMap 是按照链表排列(也用到了散列机制,所以它拥有和 HashMap 一样的查询速度).
- 了解了 Map.Entry 接口后, 我们便可以采用一种更高效的方式来遍历 Map 的 Key-Value:
for (Map.Entry<T, V> entry : Map.entrySet()){
entry.getValue();
entry.getKey();
}
图片中为什么没有Vector?
<Thinking in Java> 中说到: 新程序不应该使用过时的 Vector, Hashtable(HasMap的线程安全实现) 和 Stack.
This class is equivalent to ArrayList with synchronized operations. This has a performance cost, and the synchronization is not necessarily meaningful to your application: synchronizing each call to get, for example, is not equivalent to synchronizing on the list and iterating over it (which is probably what you intended). If you do need very highly concurrent access, you should also consider CopyOnWriteArrayList.
集合工具类:
- Arrays 提供了很多对数组操作的便利工具, 如 二分查找,局部复制,排序.....
- Arrays.asList 会返回一个基于固定容量的数组实现的 List 对象, 如果你尝试任何会改变该 List 对象的容量的操作都会得到一个 unSupportOperationException 异常, 因此如果你希望把一个数组转换成一个普通的 List, 应该使用 Collections.addAll 方法, 或者把 Arrays.asList 返回的结果作为参数传入任何 Collection 构造器中.
- Collections 提供了对集合操作的便利工具,其中一个比较常用: addAll
未完待续....对集合的深入研究和理解.