这篇的主要内容是Java基础中最重要的东西 —> 集合。
集合框架是 Java 编程中使用最频繁、最方便的。而且,无论是在日常开发,还是在面试中,这个知识点是非常重要的。
集合框架主要分为 Colletion 和 Map,这次先说说 Colletion。
Collection 接口是所有集合的根。(在这里我们先把 Map 排除,虽然在概念上,我们会把 Map 作为集合框架的一部分,但它本身并不是真正的集合。)
下面是 Collection 的框架结构图:
我们可以看到,Collection 接口提供了三大类集合,分别是 List(有序集合)、Set(不可重复的无序集合)、Queue(队列)。每种集合的通用逻辑,都会被抽象到相应的抽象类之中,比如 AbstractList 就集中了各种 List 操作的通用部分。
通过查看 Collection 接口源码可以知道,里面有许多方法是针对集合的基础操作,例如:添加、删除、获取等。下面选取部分功能来进行说明一下:
List 是有序集合,提供了方便的访问、插入、删除等操作。能够通过索引来访问 List 中的元素,而且允许有相同的元素。
List 中常用的子类有三个:ArrayList、LinkedList 以及 Vector。
它们都实现了 List 接口,因此具体功能比较近似,比如,都能按照位置进行定位、添加或删除的操作,都提供迭代器遍历内容等。
Vector、ArrayList 与 LinkedList 的区别:
Vector:是线程安全的动态数组,内部使用对象数组来存储数据。每次扩容都会提高一倍容量。它的线程安全,是通过在方法上添加 synchronized 关键字来实现的。
ArrayList:也是动态数组,但它不是线程安全的。每次扩容都会增加原容量的 50%。
LinkedList:双向链表,不是线程安全的。
Set 是无序集合,不允许有重复元素,也就是不存在两个对象 equals 判断返回 true。
Set 中常用的子类有三个:TreeSet、HashSet 以及 LinkedHashSet。
TreeSet:支持自然顺序访问,也就是说是有序的,但是添加、删除、包含等操作相对低效一点(时间复杂度为 O(logn))。
HashSet:无序的,利用哈希算法实现。理想情况下,如果散列正常,添加、删除、包含等操作的时间复杂度为常数级。
LinkedHashSet:继承于 HashSet。在内部构建了一个记录插入顺序的双向链表,因此,支持按插入顺序遍历,也保证了常数级的添加、删除、包含等操作。
通过查看上述的 Set 集合的源码可知,TreeSet 利用了 TreeMap 实现的,而 HashSet 是利用 HashMap 实现的。Java 类库创建了一个 Dummy 对象 “PRESENT” 作为 value,所有插入的元素都以键的形式存放。
Queue 是 Java 提供的标准队列结构的实现,除了提供集合的基本操作之外,它还支持先入先出(FIFO,First In First Out)或后入先出(LIFO,Last In First Out)的行为。
尝试在已满队列添加一个新元素时,add() 方法会抛出一个 IllegalStateException 异常,而 offer() 方法则是返回 false。
尝试在空队列删除头部元素时,remove() 方法会抛出 NoSuchElementException 异常,而 poll() 方法则是返回 null。
尝试在空队列查看头部元素时,element() 方法会抛出 NoSuchElementException 异常,而 peek() 方法则是返回 null。
Queue 的常用子类有:
PriorityQueue:优先级队列
DelayQueue:延迟队列
ArrayBlockingQueue:基于数组的阻塞队列
LinkedBlockingQueue:基于链表的阻塞队列
SynchronousQueue:同步阻塞队列
因为 Queue 通常被用在并发编程场合,所以,在写到并发包时,再详细介绍。
这篇主要概况了 Collection 的要点,并没有深入地去讲解各种集合类。
上述讲到 List 和 Set 的集合类都不是线程安全的,但是并不是说没用了,我们可以通过 Colletions 工具类,来实现基本的线程安全集合。
具体方法如下:
List list = Collections.synchronizedList(new ArrayList());
Set s = Collections.synchronizedSet(new HashSet());
以上皆为本人学习时的笔录总结。若文章有错误之处,欢迎大家指正。