首页 > 代码库 > Java Collections Framework

Java Collections Framework

集合OR 容器
通常我们会用数组去保存一些基本数据类型,数组是编译器支持的类型,但是数组的一个明显缺点就是具有固定尺寸,而在一般情况下,只有在程序运行的时候,我们才能知道要保存的具体数目。
Java类库提供了一套相当完善的容器框架(Collections Framework)来解决这个问题。其中基本的类型是List、Set、Queue和Map。这些对象类型也被称为集合类,但是由于Java中使用了Collection这个名称指代该类库的一个子集,所以一般使用更广泛的术语“容器”来称呼它们。
容器的基本任务是保存对象,更准确的说是保存对象的引用。但是各种容器的实现是存在很大差异的,没有一种容器是绝对优秀的能够适应所有的应用场景,所以我们需要了解各种容器的底层实现,然后根据实际的情况选择合适的容器。从下面的这张容器的分类图中就能看到Collections Framework的庞大,而且这还不包括Queue接口的实现(PriorityQueue以及各种风格的BlockingQueue等)、ConcurrentMap接口实现、CopyOnWriteArrayList和CopyOnWriteArraySet、EnumSet和EnumMap、以及Collections工具类中的多个工具方法。




Interface接口规范Collections Framework定义了一些接口规范,那些常用的容器都会继承某些接口规范,每一种接口都对应给出相应的抽象类,如果类库提供的容器不能很好的完成你指定的任务,你可以扩写这些抽象类的子类,定制自己的容器。

Collection接口:仅仅表示一组对象的集合,而没有指定对象的存放次序,以及能否包含重复元素,Collection接口自身还继承了Iterator接口。
下面要说的很多容器都实现了Collection接口,包括List、Set、Queue、Deque等接口。需要注意的是,同为容器的Map没有实现Collection接口。
Collection接口定义了容器最基本的一些特性,包含以下的接口方法定义:
  • size方法:返回容器中元素的个数
  • isEmpty方法:返回容器是否为空
  • contains方法:返回容器中是否包含某个元素
  • iterator方法:返回容器的迭代器
  • add方法:用于向容器中添加元素
  • remove方法:用于删除容器中的元素
  • clear方法:清空容器中的元素
  • toArray方法:将容器类转成相应的对象数组


List接口:List继承于Collection接口,表示一个有序容器,容器内的元素会按照加入的顺序有序的存放,允许出现重复的元素,可以基于元素位置的访问。
List接口在Collection接口的基础上加上了以下方法的定义,
  • get方法:获取指定位置的元素
  • set:将指定位置设置成指定的元素
  • indexOf:获取指定元素在容器中的位置
  • listIterator:返回ListIterator类型的迭代器
  • subList:根据区间位置,获取容器的子容器

List接口的常见实现类有ArrayList、LinkedList、Vector等



Set接口:继承于Collection接口,特点是不能存放相同的元素,对有序性没有要求,Set接口中的方法定义基本和Collection接口一致,没有加入新的方法定义。

常见的Set接口的实现有HashSet、SortedSet接口


Queue接口:继承于Collection接口,是一个被定义用来存放一系列等待进行某个过程元素的容器,除了一些基本的容器操作,Queue队列还提供了一些额外的插入、提取和检查的操作。

Queue接口中定义以下的方法:
  • add方法:将指定的元素插入此队列(如果立即可行且不会违反容量限制),在成功时返回 true,如果当前没有可用的空间,则抛出 IllegalStateException。
  • offer方法:将指定的元素插入此队列(如果立即可行且不会违反容量限制),当使用有容量限制的队列时,此方法通常要优于 add(E),后者可能无法插入元素,而只是抛出一个异常。
  • peek方法:获取但不移除此队列的头;如果此队列为空,则返回 null。
  • pool方法:获取并移除此队列的头;如果此队列为空,则返回 null。
  • remove方法:获取并移除此队列的头。
包括Deque、BlockingQueue接口都直接继承与Queue接口


Map接口:是一个关于key(键)和value(值)的映射集合,每一个key对应一个value。

Map接口中定义的一些基本方法:
  • size方法:返回容器中元素的个数
  • put方法:向容器中加入元素
  • remove方法:删除容器中元素
  • isEmpty方法:判断容器是否为空
  • contains方法:判断容器是否包含指定元素
  • clear方法:清除容器中的元素
  • keySet方法:返回Map的key集合,是Set类型的
实现了Map接口的一些类:HashMap、Hashtable、WeakHashMap、SynchronizedMap、ConcurrentMap接口等


Deque接口:继承于Queue接口,在JDK1.6中被加入,也叫做双端队列,即可以在队列的两端进行插入和提取操作。
Deque接口在Queue接口的基础上,加上了addFirst、addLast、offerFirst、offerLast等方法,分别表示这些操作可以在两端进行。

常见的Deque的实现类:ArrayDeque、ConcurrentLinkedDeque、LinkedList、BlockingDeque等。


Collections Framework中还包含一些其他的接口,但基本由上述接口扩展而来,如SortedSet、SortedMap、BlockingQueue、BlockingDeque、ConcurrentMap等

______________________________________________________________________________________________________________________________________________________________________

通用的一些实现类
类库提供了一些非常有用的基于上述接口的容器实现类,并且能够很好的胜任日常开发中的大部分的场景。

HashSet:基于Set接口的Hash表的实现,比较全面的实现了Set接口。元素在容器的中的顺序是无序的,底层是基于HashMap的实现,key表示set容器中国的值,value都是一个相同的对象,HashMap的put方法。

TreeSet:基于红黑树实现,继承于NavigableSet接口,NavigableSet也就是SortedSet的扩展,具有了为给定搜索目标报告最接近匹配项的导航方法。

LinkedHashSet:继承与HashSet类,实现了Set接口,具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。

ArrayList:实现了List接口,底层基于数组实现,对元素的随机访问速度较快,但是插入和删除操作速度较慢。

LinkedList:实现了List接口和Deque接口,底层是双重链表实现,对于元素的插入和删除操作较快,但是随机访问的性能较差。当通过队列使用时,LinkedList表现为一个FIFO队列。

ArrayDeque:实现了Deque,是Deque接口一个非常高效的基于数组的实现。

PriorityQueue:是一个基于优先级堆的无界优先级队列

HashMap:基于哈希表的Map接口的实现,允许使用NULL值和key,除了非同步和可以使用null之外,和HashTable大致相同,

TreeMap:基于红黑树的NavigableMap实现,其中的映射根据其键的自然顺序或者创建的时候提供的Comparator进行排序。

LinkedHashMap:Map接口的哈希表和链表实现,具有可预期的迭代顺序。

_________________________________________________________________________________________________________________________________

包装实现类
在java.util.Collections工具类中提供了一系列的静态内部类容器,这些内部类也实现了Collection接口,并且具有各自的特性,可以分为以下三类:
  • Collections.unmodifiableInterface返回指定Interface类型的容器,但是不允许用户去修改它们。相当于原来容器的一个不能修改的视图。
  • Collections.synchronizedInterface:返回指定interface类型的容器,但是是线程安全的。
  • Collections.checkedInterface返回指定 interface 的一个动态类型安全视图。试图插入一个错误类型的元素将导致立即抛出ClassCastException
___________________________________________________________________________________________________________________________________

基于特点目的的实现

WeakHashMap:我们说容器是用来保存对象的,更准确的说是用来保存对象的引用,如果一个长生命周期的容器,保持着一个无用对象的引用,就会造成GC无法回收。weakHashMap弱键 实现的基于哈希表的 Map。在 WeakHashMap 中,当某个键不再正常使用时,将自动移除其条目。更精确地说,对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的丢弃,这就使该键成为可终止的,被终止,然后被回收。丢弃某个键时,其条目从映射中有效地移除,因此,该类的行为与其他的Map 实现有所不同。
IdentityHashMap:此类利用哈希表实现Map 接口,比较键(和值)时使用引用相等性代替对象相等性。换句话说,在IdentityHashMap 中,当且仅当 (k1==k2) 时,才认为两个键 k1k2 相等。
CopyOnWriteArrayList:ArrayList的一个线程安全的变体,其中所有可变操作(addset 等等)都是通过对底层数组进行一次新的复制来实现的,一般需要很大的开销。
CopyOnWriteArraySet:内部使用CopyOnWriteArrayList的Set
EnumSet:与枚举类型一起使用的专用的Set实现。枚举 set 中所有键都必须来自单个枚举类型,该枚举类型在创建 set 时显式或隐式地指定。
EnumMap与枚举类型一起使用的专用的Map实现。枚举映射中所有键都必须来自单个枚举类型,该枚举类型在创建映射时显式或隐式地指定。枚举映射在内部表示为数组。此表示形式非常紧凑且高效。

——————————————————————————————————————————————————————————————————————
用于并发用用的实现类

ConcurrentLinkedQueue:一个基于链接节点的无界的线程安全的队列,按照FIFO原则对元素进行排序。
ConcurrentHashMap:支持获取的完全并发和更新的所期望可调整并发的哈希表,是基于非阻塞实现的。
LinkedBlockingQueue:一个基于已链接节点的、范围任意的blocking queue,也是按照FIFO排序元素。
PriorityBlockingQueue:一个带有优先级的阻塞队列的实现。

其他的并发容器可以在java.util.concurrent包下面找到




Java Collections Framework