对象的容纳
程序设计过程中,为了方便容纳和操作对象, JAVA提供了多种方式。
数组
- 数组是JAVA内建的类型,作为容纳对象的一种方式。
- 数组是相同类型元素的集合,内存中分配一块连续的内存区域,通过数组下标索引计算出元素对应内存区域的存储地址。
- 数组可以高效的访问元素,但是数组的创建时就必须指定数组的大小。
集合类
集合类是一系列实现抽象数据结构的类集合,这些类为容纳和操作对象提供了不同形式的实现。
常见数据结构
数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合
- 集合:
数据结构中的元素之间除了“同属一个集合” 的相互关系外,别无其他关系; - 线性结构
数据结构中的元素存在一对一的相互关系; - 树形结构
数据结构中的元素存在一对多的相互关系; - 图形结构
数据结构中的元素存在多对多的相互关系。
参考:
百度百科-数据结构
Java 1.2之前集合类
java 1.2版本之前,只提供了几种有限的集合类的实现:
Vector
(矢量)、BitSet
(位集)、Stack
(堆栈)、Hashtable
(散列表).
Vector
(矢量):自增长的对象数组的实现。 内部使用数组存储对象,当容量大于数组长度时,创建一个大于原数组大小的新数组,将原数组数据复制到新数组,再将新数组赋值给原数组。BitSet
(位集):自增长的位向量实现。内部使用long数组存储各个位向量值(0,1),通过逻辑与(&
),逻辑或(|
),逻辑非(~
)来操纵位向量的值。Stack
(堆栈): 一种“后入先出”(LIFO
)集合。继承Vector
封装push
,pop
,peek
操作。Hashtable
(散列表): 哈希表数据结构的实现(哈希表:根据关键码值(Key Value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度:百度百科-哈希表)。内部通过数组链表来存储对象,通过对象的哈希值来映射数组下标来查找和存储对象。如果映射的数组下标已存在对象(冲突),则把对象链接到此下标对应的链表头部,如果冲突超过阀值,则进行扩容数组链表大小和复制原有对象到新数组链表(rehash
操作)。
Java 1.2集合类
由于Java 1.2之前有限的集合类和混乱的设计,Java 1.2对集合进行了完全的重新设计。 并将这些集合类归集成java.util库的一部分。新的集合库考虑了“容纳自己对象”的问题,并将其分割成两个明确的概念。
- 集合(
Collection
):一组单独的元素,通常应用了某种规则。 在这里,一个 List(列表)必须按特定的顺序容纳元素,而一个Set
(集)不可包含任何重复的元素。相反,“包”(Bag)的概念未在新的集合库中实现,因为“列表”已提供了类似的功能。 - 映射(
Map
):一系列“键-值”对(这已在散列表身上得到了充分的体现)。 简单地在一
个Map 里包含其他Map
(后者又可以包含更多的Map
,以此类推)。
新的集合类示意图:
示意图说明
- 虚线框代表“接口”。
- 点线框代表“抽象”类。
- 实线框代表普通(实际)类。
- 点线箭头表示一个特定的类准备实现一个接口(在抽象类的情况下,则是“部分”实现一个接口)。
- 双线箭头表示一个类可生成箭头指向的那个类的对象。例如,任何集合都可以生成一个枚举器(
Iterator
),而一个列表可以生成一个ListIterator
(以及原始的枚举器,因为列表是从集合继承的)。
框架分析
- 接口(
Collection
(List
,Set
),Map
): 提供集合类的通用行为。如Collection
定义了集合类操作最基础的行为:添加,删除,迭代对象等操作,以达到最大通用性。Map定义键映射值的最基本行为。 List(有序对象集合),Set
(无重复对象集合)扩展Collection
接口,定义自己的独有规则操作对象的行为。 - 抽象类(
AbstractCollection
(AbstractList
,AbstractSet
),AbstractMap
):提供基本接口的骨干实现,最小化实现子类的共有行为。 便于以此类为基础定制特有规则的集合类,一般无需关注此类,除非需要自定义集合类。 - 实现类:继承抽象类,实现特有规则的集合类,如:
ArrayList
,LinkedList
,HashMap
,TreeMap
等。 - 遗留类(
Vector
,Stack
):Vector
,Stack
为Java 1.2之前版本实现的集合类,已经可以用现有的类来替代这些类的来使用。如ArrayList
替换Vector
,Deque
(java 1.2版本未实现)替换Stack
。保留这些类是为了兼容已有代码。 - 迭代器(反复器)(
Iterator
,ListIterator
): 迭代容器元素是一种通用高频的行为,迭代器(反复器)定义了访问这些元素的通用行为。 通过上溯造型成迭代器接口就具备了迭代所有集合类的方法,因为此迭代器在所有实现类中都进行了实现(多形性)。 - 比较器(
Comparable
,Comparator
): 排序容纳元素是一种通用高频行为,但是各个对象的比较规则又是各不相同。将这些对象易于变化的部分分离出来是设计此类的理念所在。Comparable
定义对象的比较行为,集合类中使用Comparable
以此屏蔽对象的具体比较规则(类的多形性特性)。 - 工具类(
Collections
,Arrays
): 提供操作集合和数组的便利方法,以及集合之间的转换等方法。
集合类实现类简要分析
ArrayList
:List
接口的数组实现,替换原有的Vector,允许我们快速访问集合元素。因为数组内存连续分布的特性,可以通过数组下标可以快速访问元素;插入和删除需要移动插入或删除下标元素之后的所有元素,所以其效率比较低效;ArrayList会自适应数组容量,当数组元素个数超过数组容量时会自动进行扩容。LinkedList
:List
接口的链表实现,允许我们快速插入和删除集合元素。链表是一种非连续、非顺序的存储结构,由一系列节点和指向其他节点的指针(引用)所组成。 插入和删除元素,只需要变动几个节点的指针的指向即可完成操作,所以LinkedList
的插入和删除具有很高的效率,但是查找元素因为需要通过指针指向从头开始查找集合的元素元素,所以其查找的效率比较低效。HashSet
:Set
接口的哈希表实现。Set规定了添加到集合的元素必须是无重复的,添加到集合中的元素必须重写equals
和hashCode
来保证元素之间的唯一性。HashSet
内部使用HashMap
的实例进行实现。TreeSet
:Set
接口的红黑树实现,红黑树是每个节点带有颜色的自平衡的二叉查找树,节点非黑即白。二叉查找树首先是一个完全二叉树并且是有序的(从左子树到右子树之间是存在顺序的),红黑树的这些特性保证了TreeSet
元素之间的顺序。HashMap
:Map
接口的哈希表实现用来代替Hashtable
,Map
维持了键值对的关系,通过键来查找其相应的值。内部通过数组链表进行实现,通过哈希表的散列函数将Map的键映射到数组的下标进行快速访问;如果映射的数组下标已存在对象(冲突),则把对象链接到此下标对应的链表头部,如果冲突超过阀值,则进行扩容数组链表大小和复制原有对象到新数组链表(rehash
操作)。TreeMap
:Map
接口的红黑树实现。TreeMap
是键值对按键有序,为了实现Key
有序,要求Key
实现Comparable
接口或者构造时传入Comparator
以此来保证Key的顺序。
工具类
Java1.2新增
Arrays
和Collections
两个实用工具,用来对数组或者列表进行排序和搜索。
Arrays
:包含操作数组排序和搜索的各种方法,此类还包含一个允许将数组作为列表来查看的静态工厂。Collections
:包含操作列表排序和搜索的各种方法,同时还包含其他大量实用的有用工具(如:max
,min
等)。
可比较与比较器
为了便于集合元素之间的比较排序,JDK提供了Comparable
和Comparator
来进行元素之间的比较。元素实现Comparable
接口的compareTo
来规定元素是可比较的,方便集合对这些元素进行排序比较,Comparator
则在集合外通过compare
方法来定义元素之间的比较规则。