前言:
在平常的写java程序中,常用除了8种常用数据类型,String对象外,还有集合类,例如ArrayList,HashMap等,这些最常用。
一、List接口
List接口为Collection直接接口。List所代表的是有序的Collection(容器),即用某种特定的插入顺序维护元素顺序。使用者可以对列表中每个元素插入的位置进行精确的控制。然后可以根据元素的整数索引访问元素,并搜索列表中的元素。例如:get(1);实现List接口的集合主要有:ArrayList、LinkedList、Vector、Stack。
1-1:ArrayList
ArrayList是一个动态数组,也是我们使用最多的集合。它允许任何符号规则的元素插入(包括null)。每一个ArrayList都有一个初始容量(10),该容量代表了数组的大小。随着容器的元素不断增加,容器的大小也会自动增加,在每次向容器中增加元素的同时都会进行容器检查,当快溢出时,就会进行扩容操作。(如果我们明确所插入的元素的多少,最好指定一个初始容量值,避免过度的进行扩容操作而影响程序性能。)
常用的操作:size,isEmpty,get,set,iterator 和 listIterator,都是以固定时间运行。
ArrayList 擅长随机访问,因为基于动态数组的数据结构原因。(联想物理存址的概念)
(非同步的,多线程访问下同一个List,需要实现访问同步)
1-2:LinkedList
LinkedList是一个双向链表,除了有ArrayList的基本操作以外,还额外提供了get,remove,insert方法在LinkedList的首部或尾部。由于LinkedList是基于双重链表的数据结构,所有操作都要按照该数据结构执行,在列表中索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端),可以通过较低的代价在List中进行插入和删除操作。(联想链表的物理存址方便性)
与ArrayList 一样,(非同步的,多线程访问下同一个List,需要实现访问同步)
1-3:Vector
与ArrayList相似,但是Vector是同步的。Vector是线程安全的动态数组。它的操作与ArrayList几乎一样,(但是写代码时候很少用到,也不知道为什么。)
1-4:Stack
Stack继承自Vector,实现一个后进先出的堆栈。Stack提供5个额外的方法使得Vector得以被当作堆栈使用。基本的push和pop 方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。
(但是写代码时候很少用到,也不知道为什么。)
二、Set接口
set是一种不包括重复元素的Collection。它维持自己的内部排序,并不能随机访问,与List一样,允许null的存在,但是仅有一个,由于Set接口的特殊性,传入Set集合中的元素都必须不同,同事要注意任何可变对象,如果在对集合中元素进行操作时,导致e1.equals(e2)==true,则必定会产生某些问题。
Set接口的集合有:EnumSet、HashSet、TreeSet
:2-1:EnumSet
一看Enum就知道是枚举的Set,所有元素都是枚举类型。因为其内部是以HashCode来实现的,内部
2-2:HashSet
HashSet堪称查询速度最快的集合,因为其内部是以HashCode来实现的,内部元素的顺序由哈希码来决定,所以迭代顺序不清楚。
2-3:TreeSet
基于TreeMap,生成一个总是处于排序状态的set,内部以TreeMap来实现。是使用元素的自然顺序对元素进行排序,或者根据创建Set是提供的Comparator进行排序,具体取决于使用的构造方法。
三、Map接口
Map与List、Set接口不同,他是由一系列键值对组成的集合,提供了key-value的映射,同时也没有继承Collection。在Map中,他保证了key与value之间的对应关系,不会存在相同的key,Map的put方法不允许key重复的。
3-1:HashMap
一看就知道是以哈希表数据结构实现,查找对象时,通过哈希函数计算其位置,为了快速查询。内部定义了一个hash表数组(Entry[ ] table),元素会通过哈希转换函数将元素的哈希地址转换成数组中存在的索引,如果有冲突,则使用散列链表的形式将所有相同的哈希地址的元素串起来,是一个单链表结构。
3-2:TreeMap
key是以某种排序规则排序,内部以red-black Tree(红黑树)的数据结构实现,实现了SortedMap接口
3-3:HashTable
也是哈希表数据结构的Map,线程安全,适用于同步操作,所以性能比HashMap要低。
四、Queue
队列,它主要分为两大类,一类是阻塞式队列,队列满了以后再插入元素则会抛出异常,主要包括ArrayBlockQueue、PriorityBlockingQueue、LinkedBlockingQueue。另一种队列则是双端队列,支持在头、尾两端插入和移除元素,主要包括:ArrayDeque、LinkedBlockingDeque、LinkedList。
五、相互区别
Vector 和 ArrayList
(1)Vector是线程同步的,所以他也是线程安全的,而ArrayList是线程异步,不安全,一般不考虑多线程情况下,使用ArrayList效率高。
(2)如何集合中元素的数目大于目前集合数组的长度时,Vector增长率为当前数组长度的100%,而ArrayList增长率为50%,考虑到集合使用数据比较大时,使用Vector比较好。
(3)查找指定位置的数据,Vector和ArrayList使用时间是相同的。而移动数据位置最快是LinkedList。
(4)ArrayList 和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,都允许直接序号索引元素,但是插入数据要设计到数组元素移动 等内存操作,所以索引数据快插入数据慢,Vector由于使用了synchronized方法(线程安全)所以性能上比ArrayList要 差,LinkedList使用双向链表实现存储,按序号索引数据需要进行向前或向后遍历,但是插入数据时只需要记录本项的前后项即可,所以插入数度较快
ArrayList和LinkedList
1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。 3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。 这一点要看实际情况的。若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList。但若是批量随机的插入删除数 据,LinkedList的速度大大优于ArrayList. 因为ArrayList每插入一条数据,要移动插入点及之后的所有数据。
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没有调优选项,因为该树总处于平衡状态。
Hashtable与Hashmap
1、历史原因:Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现 。
2、同步性:Hashtable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步的 。
3、值:只有HashMap可以让你将空值作为一个表的条目的key或value 。