一、集合概述
集合类不同于数组,只能保存对象(即对象的引用变量),Java集合类大致可分为Set、List、Queue、Map四种体系,派生于Collection和Map两个接口。各集合大类主要区别如下:
1. Set代表无序、不可重复的集合
2. List代表有序、可重复的集合
3. Map具有映射关系的集合
4. Queue代表队列集合
二、Set集合
Set集合有HashSet、TreeSet和EnumSet三个实现类,且都是非线程安全的,可通过Collections工具类的synchronizedSortedSet来实现线程安全,示例代码如下
SortedSet s = Collections.synchronizedSortedSet(new TreeSet());
以上Set集合特点如下:
1、HashSet
按Hash算法存储集合中的元素,具有很好的查找和存取性能。
通过获取对象的HashCode值决定存储位置。
非线程安全,多个线程同时修改集合时,需要通过代码保证其同步。
HashSet集合判断两个元素相等的标准是两个对象通过equals方法比较相等,并且两个对象的HashCode值也相等。
2、LinkedHashSet(HashSet的子类)
同样通过获取对象的HashCode值决定存储位置。
有序,不同于HashSet,其使用链表维护元素次序(根据元素插入顺序排序)
性能略低于HashSet,但是迭代访问元素具有很好的性能。
3、TreeSet
有序,SortedSet接口的实现类,与HashSet不同的是其为根据元素值的大小进行排序。
采用红黑树的数据结构存储集合元素。
支持自然排序和定制排序,默认采用自然排序。
其中自然排序调用集合元素的compareTo(Object obj)方法来比较元素大小。需实现Comparable接口。
通过compareTo(Object obj)方法比较两个对象是否返回0作为两对象是否相等的唯一标准。
定制排序,例如想按降序排序,可通过Compartor接口实现,Java8可使用Lambda表达式代替Comparator对象。
4、EnumSet
专为枚举类设计的集合,所有元素必须是指定枚举类型的枚举值。在创建EnumSet时显式或隐式地指定。
有序,以枚举值在Enum类内的定义顺序进行排序。
元素在Enum内部以位向量的形式存储,非常紧凑高效。因此,EnumSet对象占用内存很小且运行效率好,尤其是批量操作。
不允许插入null,负责EnumSet将抛出空指针异常。
5、Set集合的选择
HashSet的性能总是好于TreeSet,所以当需要保持排序的Set时,才使用TreeSet,否则都应使用HashSet。另外当需要遍历Set集合时,应选择LinkedHashSet,由于使用了链表,所以遍历会更快。EnumSet是性能最好的,但只能保存同一个枚举类的值作为集合元素。
三、List集合
List集合的实现类有ArrayList、Vector,其中ArrayList是非线程安全的,Vector是线程安全的。两者用法几乎完全相同,但Vector
是比较古老的集合类,所以尽量少用。其中Vector还提供了一个Stack子类,用于模拟“栈”数据结构(即后进先出LIFO)。
List集合使用建议:
1、如果需要遍历List集合元素,对于ArrayList、Vector集合,应该使用随机访问方法(get)来遍历集合元素;对于LinkedList集合,应该采用迭代器(Iterator)来遍历集合元素。
2、如果需要经常执行插入,删除操作来改变包含大量数据的List集合的大小,可考虑使用LinkedList集合,使用ArrayList、Vector集合可能需要经常重新分配内部数组大小,效果比较差。
3、如果有多个线程需要同时访问List集合中的元素,开发者可考虑使用Collections工具类将集合包装成线程安全的集合。
四、Queue集合
Queue集合实现类有PriorityQueue、ArrayDeque、LinkedList,用于模拟队列这种数据结构,队列通常指先进先出(FIFO)的容器。队列头部保存先存放进的元素,尾部存放后放进的元素,队列不允许随机访问其内部元素。元素插入到尾部,访问返回头部元素。
1、PriorityQueue
按队列的元素大小进行重新排序,所以不是绝对标准的队列。因此违反了队列的基本规则(先进先出FIFO)。
不允许插入null
有自然排序和制定排序。
2、ArrayDeuqe
基于数组实现的双端队列,允许从两端操作队列的元素,且可以当作栈来使用。
3、LinkedList
同时实现了List和Deque两个接口,因此可作为List集合、双端队列、栈使用。ArrayList、ArrayDeque内部以数组的形式保存集合中的元素,因此随机访问集合元素有较好性能,而LinkedList内部以链表的形式来保存集合中的元素,因此随机访问元素性能较差,但是插入、删除元素时性能比较出色(只需改变指针所指的地址即可)。
五、Map集合
Map集合实现类有HashMap、Hashtable、LinkedHashMap、WeakHashMap、IdertityHashMap、TreeMap、EnumMap等。从源码中可以看出,Java是先实现了Map,然后通过包装一个所有value都为null的Map就实现了Set集合。
1、HashMap
非线程安全
判断两个key相等的标准:两个key通过equals()方法返回true,两个key的hashCode值也相等。
最多只有一个key-value对的key为null,但无数多个key-value的value可以为null。
2、Hashtable
线程安全,比较古老的集合类。
不允许使用null作为key和value,如果试图把null值放进Hashtable中,将会引发NullPointerException异常
3、LinkedHashMap
有序,以链表来维护内部顺序,降低了性能,但迭代访问其内部元素有较好性能。
4、TreeMap
采用红黑树数据结构,根据key节点进行排序。
有自然排序和定制排序两种方式。