在没有集合类之前,Java用数组可以存储对象。为了使程序方便地存储和操纵数目不固定的一组数据,JDK中提供了Java集合类,所有Java集合类都位于Java.util包中。
1.集合框架
Java 集合框架主要包括两种类型的容器,一种是Collection,存储元素集合;另一种是Map,存储键/值对映射。
2.常见接口
2.1.Collection
Collection是最基本的集合接口。可以容纳一组集合元素。
2.2.List
List接口是一个有序的Collection,每个元素都有索引下标,使用此接口能够准确的控制每个元素插入的位置。允许有多个null元素。
2.3.Set
Set接口无重复的元素。最多有一个null元素。
2.4.Map
Map接口用于保存具有映射关系的数据,提供key(键)到value(值)的映射。一个Map中不能包含相同的键,每个键只能映射一个值。
2.5.List与Set
- Set接口存储的是无序的,不重复的数据。List接口存储的是有序的,可以重复的元素。
- Set查找元素效率低下,插入删除效率高,插入删除不会引起元素位置改变;List查找元素效率高,插入删除效率低,因为会引起其他元素位置改变。
3.常见实现类
3.1.继承自List
3.1.1.ArrayList
ArrayList的底层数据结构是一个数组,查询通过数组下标查询,查询速度快,增删慢,线程不安全。
3.1.2.LinkedList
LinkedList的底层数据结构是一个链表,增删元素快,查询慢,线程不安全。
3.1.3.Vector
Vector的底层数据结构也是一个数组,查询速度快。它的方法上加了synchronized关键字,所以它是线程安全的,但也因此它的效率很低。
3.2.继承自Set
3.2.1.HashSet
HashSet的底层数据结构是哈希表,元素无序且唯一,线程不安全,效率高。具有很好的插入、查询、删除性能。
3.2.2.TreeSet
TreeSet的底层数据结构是红黑树,元素唯一且已经排好序,线程不安全,效率高。根据构造方法不同,分为自然排序(无参构造)和比较器排序(有参构造),自然排序要求元素必须实现Comparable接口,并重写compareTo()方法;比较器排序需要传入一个实现Comparator接口的比较器对象,或者采用匿名内部类的方式new一个Comparator对象,重写里面的compare()方法。
3.2.3.LinkedHashSet
LinkedHashSet的底层数据结构是链表+哈希表,元素唯一。根据元素的hashCode值来决定元素的存储位置,但它同时使用双向链表维护元素的次序,这使得元素看起来是以插入顺序保存的。插入性能略低于HashSet。
3.3.继承自Map
3.3.1.HashMap
HashMap的底层数据结构,在JDK 7及以前是数组+链表结构,JDK 8及以后是数组+链表+红黑树。线程不安全。
当HashMap中的元素越来越多的时候,哈希冲突的几率也就越来越高,因为数组的长度是固定的。为了提高查询的效率,当超过数组的length*loadFactor时,会对HashMap的数组进行扩容,而在HashMap数组扩容之后,原数组中的数据必须重新计算其在新数组中的位置并放入,即resize。当HashMap中的其中一个链的对象个数如果达到了8个,此时如果capacity没有达到64,HashMap会先扩容解决,如果已经达到了64,那么这个链会变成树。
HashMap的key值可以为null,但只能有一个key为null。
如果需要同步,可以用Collections的synchronizedMap方法,或者使用ConcurrentHashMap。
3.3.2.LinkedHashMap
LinkedHashMap是HashMap的子类,在HashMap存储结构的基础上,使用了一对双向链表来记录添加元素的顺序。
3.3.3.TreeMap
TreeMap的底层数据结构是红黑树,元素已经排好序,线程不安全,效率高。根据构造方法不同,分为自然排序和比较器排序,自然排序要求Key必须实现Comparable接口且所有的 Key 应该是同一个类,并重写compareTo()方法;比较器排序需要传入一个实现Comparator接口的比较器对象,重写里面的compare()方法。
3.3.4.Hashtable
Hashtable和HashMap有很多相似之处,底层数据结构是数组+链表,不同的是它承自Dictionary类,线程安全。Hashtable不允许key和value为null,并发性不如ConcurrentHashMap。
3.3.5.Properties
Properties类是Hashtable的子类,用于处理属性文件。Key和Value都是字符串类型。