java2提出了collection的概念,本文对collection框架进行分析,并对java2之前的容器进行回顾。
0x01 从Arraylist说起
什么是集合,简单地说,集合类似可以自适应、动态增长的数组,这也是提出集合概念的一个初衷。
最常见的Arraylist就是集合框架下的一员,准确的说它是一个实现了Collection接口的实现类,内部通过数组的形式存储数组,因此也是一个支持高效随机存储的集合,这里之所用使用高效两字是因为链式存储类型可能对外也提供随机存储操作,然而内部实现则需要多次遍历,因此从实现上并非随机存储。
public class ArrayList extends AbstractList
implements List, RandomAccess, Cloneable, java.io.Serializable
这里Arraylist是AbstractList的子类,而父类AbstractList是一个抽象类,继承自抽象类AbstractCollection,AbstractCollection实现了多数Collection interface中的方法。每一层抽象类都是对子类型的一个归类,对上一层部分接口方法进行实现或者增加新的方法。
public abstract class AbstractList extends AbstractCollection implements List
public abstract class AbstractCollection implements Collection
0x02 Collection框架成员
collection中涉及成员繁多,从各个接口到中间抽象类再到具体实现类。
java中常用的两个概念collection和collections,都是集合框架下的重要概念,前者是集合类,后者是对集合进行的操作方法,Collections类中有很多静态方法,比如之前文章我们分析过的排序算法sort,或者从一个集合获得对应的同步版本集合的方法如synchronizedList之类,还有统计类的获取最大值最小值等等。本文重点分析Collection,从顶层到常用的实现类逐级介绍。
这里有三个概念,接口,抽象类,实现类。
interface
Collection是集合的一个顶层接口,存储单独的元素。
Map是一个顶层接口,存储键值对(Map.Entry)。
Collection接口下面有两个子类,接口List和Set,分别表示有序的collection和没有重复元素的Collection,其中Set有一个子接口SortedSet,表示有序的Set。
Map有一个子接口叫做SortedMap,是按照key的升序排列的Map。
Collection
->List (有序的collection)
->Set 不重复的collection
->sortedset有序的set
Map(unique keys to values)[ map.entry]
->sortedmap(keys 升序的map)
abstract class
AbstractCollection 实现大多数的Collection接口方法
->AbstractList 继承自AbstractCollection并实现多数List接口
->AbstractSequentialList 继承自Abstractlist提供顺序访问而非随机访问
->AbstractSet 继承自AbstractCollection并实现多数Set接口
AbstractMap 实现多数map接口
concrete implementation class
Linkedlist是AbstractSequentialList 的实现类,抽象类的实现类。
Arraylist 是 AbstractList.的实现类(Implements a dynamic array by extending AbstractList.)
HashSet是AbstractSet 的实现类,使用的hashmap,组合模式。
->Linkedhashset 有序的Hashset,插入顺序。
TreeSet 是 AbstractSet 的实现类,使用树结构存储。
HashMap是AbstractMap的实现类,使用哈希存储。
->Linkedhashmap,保持插入顺序。
Treemap是AbstractMap实现类,使用树存储。
IdentityHashMap 是AbstractMap实现类,不同于一般HashMap的是判等方式,使用引用值是否相等进行判断。
这里强烈建议仔细阅读上述总结,最好比照源码,关于为何将抽象类以及接口进行这样的组织模式,我的一点心得是:**接口是对一组方法的约定,规范的此类型的行为,接口的继承则是在原先基础上进行了新行为的加入或者约束,对于实现了部分接口的抽象类则在大的方向上实现了一些方法,对于具体实现类只需根据行为差别去修改部分方法,也就是进行了逻辑上的划分,而不是每一个实现类都要将所有方法实现一遍,另一个思想就是接口很多时候是一种概念上的归纳,对类别进行划分,就像许多标志接口(如序列化,克隆等等),表示这是某一类型的概念。**Collection框架的组织另一层次上是考虑兼容性等方面,需要向前兼容旧的容器,当然java2也对旧概念进行一定的重写和组织。关于具体方法和使用的解析,源码是最好的工具,以后有机会对个人觉得有趣的地方进行一下总结分享给大家。
0x03 集合之外
集合之外也有不少数据存储的聚集。
Vector实现一个动态的数组,和Arraylist类似,不同之处在于vector是线程安全的,方法都是同步的。
Stack是vector的子类,一个后进先出的vector,只提供一个默认构造函数,除了vector的方法外,添加了一些特有方法,pop、push、peek等。
Dictionary是一个抽象类,类似于map接口的功能,过时的。
Hashtable是Dictionary的具体实现类,早期java.util的一部分。java2提出集合框架后,进行整合,源码可以看到它继承dictionary并实现map接口。
Properties是hashtable的一个子类,额外添加一些方法,比如从文件读取以及写入文件。
BitSet 位存储集合。
关于HashTable和HashMap,常见总结为前者线程安全,不允许空值,后者非线程安全,允许空的键和值。这些在源码的定义中都是说的很清楚的。Collection的提出在效率上进行了改进,我们可以看到Vector的方法实现都是有synchronized关键字去同步方法的,而Collection如果在多线程中使用需要我们对代码进行Synchronized的控制,当然针对并发Collections提供方法可以获取同步版本集合,同样java.util.concurrent并发包中也有支持并发的结合。
总结
集合框架除了集合成员外还有集合操作方法以及迭代器和比较器的概念,通过迭代器去遍历集合,比较器可以对集合排序,用于sort方法或者treemap中的排序,重点要理解集合的概念和应用场景,细节地方很多,不是一篇文章能够覆盖,本文仅是对集合框架的脉络进行一窥,小作总结。