在平常的代码开发中,集合类是经常会使用到的,比如用于列表缓存的ArrayList,用于做映射关系的Map等等
最近重点看了下java集合类的层次继承关系和内部存储结构,做个总结以便后面可以随时翻翻。
java中的集合,不管是List,Set,还是Map,都是继承自collection接口,这个接口主要定义了集合类的一些公关方法,比如isEmpty(), remove(),add()等,在使用集合类的时候除了顺序遍历,还提供了一种方便的迭代器遍历的方法,在遍历过程中需要remove元素的必须试用迭代器遍历(在删除元素时,集合内部的index会发生变化,使用顺序遍历可能会产生unindex的情况)。
为了实现迭代遍历,定义了Iterable接口,collection接口继承了Iterable接口,以支持所有集合类实现迭代遍历。
1.List
1.1 ArrayList
ArrayList 是一个动态数组,以一个数组的格式进行存储,但是可以动态增长,继承自AbstractList,实现了List接口
ArrayList是一个非线程安全的类,使用时最好在一个线程中操作,构造函数可以提供一个数组的初始化大小,不提供默认按16来进行数组的初始化,往ArrayList增加元素时,都会先判断是否还有空间存在元素,如果没有空间,则会重新申请一个
(((以前长度*3)/2)+1)大小的数组空间,并将原来的元素全部copy到新的数组中,这样会带来效率上的损耗。建议在初始化时,能够确定存储空间的尽量提供合适的初始化数组大小,避免因为数组动态扩容带来的效率损耗。
1.2 Vector
Vector 基本上很少用到了,和ArrayList很相似,唯一的不同是Vector的方法都是线程安全的,而Array List是非线程安全的,从这点上来说,ArrayList的效率要比Vector的效率高,另外Vector是以2倍的方式扩展数组容量的
1.3 LinkedList
LinkedList 同时实现了List,Deque,所以也可以用来作为双向队列使用。LinkedList是以双向列表存储的,它是按照元素的先后顺序进行存储的,所以访问也是按照顺序来访问的。
2 Set
Set 继承了Collection,Set不保存重复的元素,存入Set里的元素都是唯一的,区分存入的元素是否重复是通过调用Equals方法来进行判断,所有存入Set中的元素类必须实现Equals方法
2.1 HashSet
Hash Set是讲存入Set中的元素以Hash链表的方式存储起来,所有元素存入Set中的位置通过调用hashCode方法获取hash值来决定,所以需要设计好的hashcode方法尽量将存入的值散列开有利于提升HashSet的访问效率。
2.2 LinkedHashSet
继承与HashSet,和HashSet的唯一区别是维护了一个双向列表来维护元素的顺序,所有访问是按顺序访问
2.3 TreeSet
TreeSet继承于AbstractSet,并且实现了NavigableSet接口
TreeSet实现了一个顺序访问的不重复元素的Set,底层使用红黑树进行数据的存储,来加快访问的速度
2.4 EnumSet
EnumSet只能用来存放Enum类型的数据,也不允许重复数据,性能是最好的
3 Map
Map和Set的区别是Set只有值,而Map是一个键值对<key,value>,Set不存重复的元素,Map中的key不能相同
3.1 HashMap
和HashSet相似,用hash链表来存储,讲键值对作为一个元素存储
3.2 LinkedHashMap
类似于HashMap,但是迭代遍历它时,取得“键值对”的顺序是其插入次序,或者是最近最少使用(LRU)的次序。只比HashMap慢一点。而在迭代访问时发而更快,因为它使用链表维护内部次序
3.3 TreeMap
基于红黑树数据结构的实现。查看“键”或“键值对”时,它们会被排序(次序由Comparabel或Comparator决定)。TreeMap的特点在于,你得到的结果是经过排序的。TreeMap是唯一的带有subMap()方法的Map,它可以返回一个子树。
3.4 WeakHashMap
弱键(weak key)Map,Map中使用的对象也被允许释放: 这是为解决特殊问题设计的。如果没有map之外的引用指向某个“键”,则此“键”可以被垃圾收集器回收。