Java中两个关键数据结构
主要分为 Collection 和 Map 两个主要接口(接口只提供方法,并不提供实现),而程序中最终使用的数据结构是继承自这些接口的数据结构类
Collection的特点
•
Collection
接口并不是一个根接口,它的超级接口是
Iterator
,需要提供其遍历、移除元素
(
可选操作
)
的能力。
•
Collection
接口定义了基本的容器操作方法
。
•
remove
()
和
contains()
判断元素是否相等的依据是类似的。
–
对于
remove(Objecto)
,若
Collection
中包含的元素
e
,满足
(o==null? e==null :
o.equals
(e))
,移除其中的一个;
–
对于
contains(Objecto)
,若
Collection
中包含至少一个或多个元素
e
,满足
(o==null ? e==null :
o.equals
(e))
,则返回
true
。
•
AbstractCollection
抽象类实现了一部分
Collection
接口的方法,主要是基于
iterator
实现的,如
remove()
、
toArray
()
,以及利用本身的属性
size
实现的
size()
。如果读一下源码,可以发现虽然
AbstractCollection
利用
add()
实现了
addAll
()
,但是
add()
本身的实现是直接抛
UnsupportedOperationException
异常的。实际上
add()
是一种“可选操作”,目的是延迟到需要时再实现。
List
List中的元素是有序的,因而我们可以按序访问List中的元素,以及访问指定位置上的元素。对于“按顺序遍历访问元素”的需求,使用List的超级接口Iterator即可以做到,这也是对应抽象类AbstractList中的实现;而访问特定位置的元素(也即按索引访问)、元素的增加和删除涉及到了List中各个元素的连接关系,并没有在AbstractList中提供。
ArrayList
•
ArrayList
是最常用的
List
的实现
,
可以简单的认为是一个动态数组;实际上
ArrayList
就是用数组实现的,长度不够时,调用
Arrays.copyOf
方法,拷贝当前数组到一个新的长度更大的
数组
•
特点:
–
随机访问速度快,插入和移除性能较差
(
数组的特点
)
;
–
支持
null
元素;
–
有顺序;
–
元素可以重复;
–
线程不安全;
Vector和Stack(不建议继续使用)
•
Vector
:线程安全的动态数组
•
Stack
:继承
Vector
,基于动态数组实现的一个线程安全的栈
;
•
Vector
与
ArrayList
基本是一致的,不同的是
Vector
是线程安全的,会在可能出现线程安全的方法前面加上
synchronized
关键字;
•
Vector
:随机访问速度快,插入和移除性能较差
(
数组的特点
)
;支持
null
元素;有顺序;元素可以重复;线程安全;
•
Stack
:后进先出,实现了一些栈基本操作的方法(其实并不是只能后进先出,因为继承自
Vector
,可以有很多操作,从某种意义上来讲,不是一个栈);
•
如果要使用栈行为,应该使用
LinkedList
。
Set
Set接口模仿了数学概念上的set,各个元素不要求重复。除了这一点,几乎和Collection本身是一样的。
Set 接口有一个直接子接口 SortedSet ,该接口要求 Set 中所有元素有序。和通过 Iterable 接口依次访问所有元素的“有序”不同,这个“有序”要求 Set 包括一个比较器,可以判断两个元素的大于、小于或等于关系。此外,该接口提供了访问第一个元素、访问最后一个元素、访问一定范围内元素的方法。 SortedSet 的子接口 NavigableSet 进一步扩展了这个系列的方法,提供了诸如返回大于 / 小于元素 E 的第一个元素的方法
HashSet、LinkedHashSet和TreeSet
•
Set
接口的实现类,最大特点是不允许出现重复元素;
•
HashSet
:基于
HashMap
实现,一个性能相对较好的
Set
;
•
LinkedHashSet
:基于
LinkedHashMap
实现,一个保存了插入顺序的
Set
;
•
TreeSet
;基于
TreeSet
实现,一个实现了排序的
Set
;