最近在准备java基础知识的总结,发现对于集合类的知识点不少很杂,借鉴网上的帖子,整理以下。java
集合框架是为表示和操做集合而规定的一种统一的标准的体系结构,在java中的集合框架主要分为两部分:Collection接口和Map接口。算法
1.数据结构分类数组
1)线性表是在内存中数据的一种组织、存储的方式;一维数组、顺序表、链表、栈、队列,循环队列、散列表等结构是逻辑上的概念,是一种理念与思想,是属于线性表中的一种逻辑实现。安全
2)Java中数据结构涉及到了数组(一维、多维)、顺序表(ArrayList、Vector)、链表(LinkedArrayList、LinkedSet)、栈(stack)、队列(Queue)、散列表(HashMap)、树(TreeSet、TreeMap)等数据结构
1.集合框架主要实现类框架
2.集合框架类图异步
1)Collection是最基本的集合接口,一个Collection表明一组Object,即Collection的元素(Elements)。一些Collection容许相同的元素而另外一些不行,一些能排序而另外一些不行。Java SDK不提供直接继承自Collection的类,Java SDK提供的类都是继承自Collection的“子接口”如List和Set。函数
2)全部实现Collection接口的类都必须提供两个标准的构造函数:无参数的构造函数用于建立一个空的Collection,有一个Collection参数的构造函数用于建立一个新的Collection,这个新的Collection与传入的Collection有相同的元素。后一个构造函数容许用户复制一个Collection。性能
3)为何继承Iterable接口而不继承Iterator?测试
由于Iterator接口的核心方法next()或者hasNext()是依赖于迭代器的当前迭代位置的。 若是Collection直接实现Iterator接口,势必致使集合对象中包含当前迭代位置的数据(指针),当集合在不一样方法间被传递时,因为当前迭代位置不可预置,那么next()方法的结果会变成不可预知。 除非再为Iterator接口添加一个reset()方法,用来重置当前迭代位置。 但即便这样,Collection也只能同时存在一个当前迭代位置,而Iterable则否则,每次调用都会返回一个从头开始计数的迭代器。 多个迭代器是互不干扰的。
不一样的Collection接口的子接口的实现类返回的Iterator具体类型可能不一样,Array可能返回ArrayIterator,Set可能返回 SetIterator,Tree可能返回TreeIterator,可是它们都实现了Iterator接口。所以,客户端不关心究竟是哪一种 Iterator,它只须要得到这个Iterator接口便可,这就是面向对象的威力。
1.List接口
List是有序的Collection,使用此接口可以精确的控制每一个元素插入的位置。用户可以使用索引(元素在List中的位置,相似于数组下标)来访问List中的元素,这相似于Java的数组。和下面要提到的Set不一样,List容许有相同的元素。除了具Collection接口必备的iterator()方法外,List还提供一个listIterator()方法,返回一个ListIterator接口,和标准的Iterator接口相比,ListIterator多了一些add()之类的方法,容许添加,删除,设定元素,还能向前或向后遍历。实现List接口的经常使用类有LinkedList,ArrayList,Vector和Stack。
1)ArrayList
ArrayList实现了可变大小的数组,它容许全部元素,包括null。size,isEmpty,get,set方法运行时间为常数。可是add方法开销为分摊的常数,添加n个元素须要O(n)的时间,其余的方法运行时间为线性。
每一个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小,这个容量可随着不断添加新元素而自动增长,可是增加算法并无定义。当须要插入大量元素时,在插入前能够调用ensureCapacity方法来增长ArrayList的容量以提升插入效率。和LinkedList同样,ArrayList也是非同步的(unsynchronized)。
2)LinkedList
LinkedList实现了List接口,容许null元素。此外LinkedList提供额外的get,remove,insert方法在LinkedList的首部或尾部。这些操做使LinkedList可被用做堆栈(stack),队列(queue)或双向队列(deque),能够认为LinkedList在方法和逻辑上和ArrayList是同样的,只是在性能上有必定的区别,ArrayList适合随机访问LinkedList更适合插入和删除,在对性能没有很大要求是是能够忽略这个差异的。
注意LinkedList没有同步方法。若是多个线程同时访问一个List,则必须本身实现访问同步。一种解决方法是在建立List时构造一个同步的List:
List list = Collections.synchronizedList(new LinkedList(...));
3)Vector
Vector很是相似ArrayList,可是Vector是同步的。由Vector建立的Iterator,虽然和ArrayList建立的Iterator是同一接口,可是,由于Vector是同步的,当一个Iterator被建立并且正在被使用,另外一个线程改变了Vector的状态(例如,添加或删除了一些元素),这时调用Iterator的方法时将抛出ConcurrentModificationException,所以必须捕获该异常。
ArrayList 和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增长和插入元素,都容许直接序号索引元素,可是插入数据要设计到数组元素移动等内存操做,因此索引数据快插入数据慢,Vector因为使用了synchronized方法(线程安全)因此性能上比ArrayList要差,LinkedList使用双向链表实现存储,按序号索引数据须要进行向前或向后遍历,可是插入数据时只须要记录本项的先后项便可,因此插入数度较快!
4)Stack
Stack继承自Vector,实现一个后进先出的堆栈。Stack提供5个额外的方法使得Vector得以被看成堆栈使用。基本的push和pop方法,还有peek方法获得栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。Stack刚建立后是空栈。
2.Set接口
Set是一种不包括重复元素的Collection。它维持它本身的内部排序,因此随机访问没有任何意义。与List同样,它一样运行null的存在可是仅有一个。因为Set接口的特殊性,全部传入Set集合中的元素都必须不一样,同时要注意任何可变对象,若是在对集合中元素进行操做时,致使e1.equals(e2)==true,则一定会产生某些问题。实现了Set接口的集合有:EnumSet、HashSet、TreeSet。
1)HashSet
HashSet堪称查询速度最快的集合,由于其内部是以HashCode来实现的。它内部元素的顺序是由哈希码来决定的,因此它不保证set 的迭代顺序,特别是它不保证该顺序恒久不变。
2)TreeSet
基于TreeMap,生成一个老是处于排序状态的set,内部以TreeMap来实现。它是使用元素的天然顺序对元素进行排序,或者根据建立Set 时提供的Comparator进行排序,具体取决于使用的构造方法。
3)LinkedHashSet
底层是链表实现的,是set集合中惟一一个能保证怎么存就怎么取的集合对象,由于是HashSet的子类,因此也是保证元素惟一的,与HashSet的原理同样。
3.Queue接口
1)阻塞式队列(BlockingQueue):队列满了之后再插入元素则会抛出异常,主要包括ArrayBlockQueue、PriorityBlockingQueue、LinkedBlockingQueue。
2)双端队列(Deque):支持在头、尾两端插入和移除元素,主要包括:ArrayDeque、LinkedBlockingDeque、LinkedList。
Map与List、Set接口不一样,它是由一系列键值对组成的集合,提供了key到Value的映射。同时它也没有继承Collection。在Map中它保证了key与value之间的一一对应关系。也就是说一个key对应一个value,因此它不能存在相同的key值,固然value值能够相同。实现map的有:HashMap、TreeMap、Hashtable、Properties、EnumMap。
1)HashMap
HashMap和Hashtable相似,不一样之处在于HashMap是非同步的,而且容许null,即null value和null key。,可是将HashMap视为Collection时(values()方法可返回Collection),其迭代子操做时间开销和HashMap的容量成比例。所以,若是迭代操做的性能至关重要的话,不要将HashMap的初始化容量设得太高,或者load factor太低。
2)TreeMap
键以某种排序规则排序,内部以red-black(红-黑)树数据结构实现,实现了SortedMap接口
3)Hashtable
Hashtable继承Dictionary类实现Map接口,实现一个key-value映射的哈希表。任何非空(non-null)的对象均可做为key或者value。添加数据使用put(key,value),取出数据使用get(key),这两个基本操做的时间开销为常数。
Hashtable经过initial capacity和load factor两个参数调整性能。一般缺省的load factor 0.75较好地实现了时间和空间的均衡。增大load factor能够节省空间但相应的查找时间将增大,这会影响像get和put这样的操做。Hashtable是同步的。
1.Vector和ArrayList
1)vector是线程同步的,因此它也是线程安全的,而arraylist是线程异步的,是不安全的。若是不考虑到线程的安全因素,通常用arraylist效率比较高。
2)若是集合中的元素的数目大于目前集合数组的长度时,vector增加率为目前数组长度的100%,而arraylist增加率为目前数组长度的50%.如过在集合中使用数据量比较大的数据,用vector有必定的优点。
3)若是查找一个指定位置的数据,vector和arraylist使用的时间是相同的,都是0(1),这个时候使用vector和arraylist均可以。而若是移动一个指定位置的数据花费的时间为0(n-i)n为总长度,这个时候就应该考虑到使用linklist,由于它移动一个指定位置的数据所花费的时间为0(1),而查询一个指定位置的数据时花费的时间为0(i)。
4)ArrayList 和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增长和插入元素,都容许直接序号索引元素,可是插入数据要设计到数组元素移动等内存操做,因此索引数据快插入数据慢,Vector因为使用了synchronized方法(线程安全)因此性能上比ArrayList要差,LinkedList使用双向链表实现存储,按序号索引数据须要进行向前或向后遍历,可是插入数据时只须要记录本项的先后项便可,因此插入数度较快!
2.Aarraylist和Linkedlist
1)ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
2)对于随机访问get和set,ArrayList以为优于LinkedList,由于LinkedList要移动指针。
3)对于新增和删除操做add和remove,LinedList比较占优点,由于ArrayList要移动数据。
4)这一点要看实际状况的。若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList。但如果批量随机的插入删除数据,LinkedList的速度大大优于ArrayList. 由于ArrayList每插入一条数据,要移动插入点及以后的全部数据。
3.HashMap与TreeMap
1)HashMap经过hashcode对其内容进行快速查找,而TreeMap中全部的元素都保持着某种固定的顺序,若是你须要获得一个有序的结果你就应该使用TreeMap(HashMap中元素的排列顺序是不固定的)。HashMap中元素的排列顺序是不固定的)。
2)HashMap经过hashcode对其内容进行快速查找,而TreeMap中全部的元素都保持着某种固定的顺序,若是你须要获得一个有序的结果你就应该使用TreeMap(HashMap中元素的排列顺序是不固定的)。集合框架”提供两种常规的Map实现:HashMap和TreeMap (TreeMap实现SortedMap接口)。
3)在Map 中插入、删除和定位元素,HashMap 是最好的选择。但若是您要按天然顺序或自定义顺序遍历键,那么TreeMap会更好。使用HashMap要求添加的键类明肯定义了hashCode()和 equals()的实现。 这个TreeMap没有调优选项,由于该树总处于平衡状态。
4.Hashtable与HashMap
1)历史缘由:Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现 。
2)同步性:Hashtable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步的 。
3)值:只有HashMap可让你将空值做为一个表的条目的key或value 。
1.对List的选择
1)对于随机查询与迭代遍历操做,数组比全部的容器都要快。因此在随机访问中通常使用ArrayList。
2)LinkedList使用双向链表对元素的增长和删除提供了很是好的支持,而ArrayList执行增长和删除元素须要进行元素位移。
3)对于Vector而已,咱们通常都是避免使用。
4)将ArrayList当作首选,毕竟对于集合元素而已咱们都是进行遍历,只有当程序的性能由于List的频繁插入和删除而下降时,再考虑LinkedList。
2.对Set的选择
1)HashSet因为使用HashCode实现,因此在某种程度上来讲它的性能永远比TreeSet要好,尤为是进行增长和查找操做。
2)虽然TreeSet没有HashSet性能好,可是因为它能够维持元素的排序,因此它仍是存在用武之地的。
3.对Map的选择
1)HashMap与HashSet一样,支持快速查询。虽然HashTable速度的速度也不慢,可是在HashMap面前仍是稍微慢了些,因此HashMap在查询方面能够取代HashTable。
2)因为TreeMap须要维持内部元素的顺序,因此它一般要比HashMap和HashTable慢。