文章目录
Java所有集合类
集合类是Java数据结构的实现。Java的集合类是
java.util包中的重要内容,它允许以各种方式将元素分组,并定义了各种使这些元素更容易操作的方法。Java集合类是Java将一些基本的和使用频率极高的基础类进行封装和增强后再以一个类的形式提供。集合类是可以往里面保存多个对象的类,存放的是对象,不同的集合类有不同的功能和特点,适合不同的场合,用以解决一些实际问题。
注意: 所有Java集合类都位于Java.util包中,与Java数组不同,Java集合不能存放基本数据类型数据,而只能存放对象的引用。
Java中的集合类可以分为两大类:一类实现了 Collection接口 ,一类实现了Map接口
Collection接口
打开 JavaAPI 查阅 Collection 接口
- 可以看到Collection是一个
根接口,本身并不能被实例化,它提供很多的不同功能的子接口来使用。 - 同时,Collection接口是否线程安全由每个具体的实现类决定。
方法:
| boolean add(E e) | 增加元素到 collection 集合中 |
|---|---|
| boolean contains (Object o) | 如果此 collection 包含指定的元素,则返回 true
|
| void clear() | 移除此 collection 中的所有元素 |
| boolean equals(Object o) | 比较此 collection 与指定对象是否相等 |
| boolean isEmpty() | 如果此 collection 不包含元素,则返回 true
|
| Iterator iterator() | 返回在此 collection 的元素上进行迭代的迭代器 |
| boolean remove(Object o) | 从此 collection 中移除指定元素的单个实例,如果存在的话 |
| int size() | 返回此 collection 中的元素数 |
| Object[] toArray() | 返回包含此 collection 中所有元素的数组 |
看一下它常用的 子接口 和 实现类 有哪些?
Collection接口可以分为两大类:List接口 和 Set接口
在着重介绍这两大接口的实现类前,先简单介绍下实现了Collection接口的 其他子接口和实现类
Queue接口
队列通常(但并非一定)以 FIFO(先进先出)的方式排序各个元素。不过优先级队列和 LIFO 队列(或堆栈)例外,前者根据提供的比较器或元素的自然顺序对元素进行排序,后者按 LIFO(后进先出)的方式对元素进行排序。无论使用哪种排序方式,队列的头 都是调用 remove() 或 poll() 所移除的元素。在 FIFO 队列中,所有的新元素都插入队列的末尾。其他种类的队列可能使用不同的元素放置规则。每个 Queue 实现必须指定其顺序属性。
方法:
Deque接口
一个线性 collection,支持在两端插入和移除元素。名称 deque 是“double ended queue(双端队列)”的缩写,通常读为“deck”。大多数 Deque 实现对于它们能够包含的元素数没有固定限制,但此接口既支持有容量限制的双端队列,也支持没有固定大小限制的双端队列。
此接口定义在双端队列两端访问元素的方法。提供插入、移除和检查元素的方法。每种方法都存在两种形式:一种形式在操作失败时抛出异常,另一种形式返回一个特殊值(null 或 false,具体取决于操作)。插入操作的后一种形式是专为使用有容量限制的 Deque 实现设计的;在大多数实现中,插入操作不能失败。
此接口扩展了
Queue接口。在将双端队列用作队列时,将得到 FIFO(先进先出)行为。将元素添加到双端队列的末尾,从双端队列的开头移除元素。从Queue接口继承的方法完全等效于Deque方法双端队列也可用作 LIFO(后进先出)堆栈。应优先使用此接口而不是遗留
Stack类。在将双端队列用作堆栈时,元素被推入双端队列的开头并从双端队列开头弹出。堆栈方法完全等效于Deque方法
ArrayDeque类
| ArrayDeque() | 构造一个初始容量能够容纳 16 个元素的空数组双端队列。 |
|---|---|
| ArrayDeque(Collection c) | 构造一个包含指定 collection 的元素的双端队列,这些元素按 collection 的迭代器返回的顺序排列。 |
| ArrayDeque(int capacity) | 构造一个初始容量能够容纳指定数量的元素的空数组双端队列。 |
方法:
-
增加方法:
addFirst(E e) add(E e) addLast(E e):前者为在双端队列头增加,后两个为在末尾增加
offerFirst(E e) offer(E e) offerLast(E e):与上相同
push(E e) 将元素推入此双端队列所表示的堆栈顶。
-
获取方法:
element() peek() peekFirst() getFirst():获取,但不移除此双端队列所表示的队列的头。
getLast() peekLast() :获取,但不移除此双端队列所表示的队列的尾。
poll() pollFirst() pollLast :获取并移除元素
clear():移除所有元素
-
删除方法:
remove() remove(Object o) removeFirst() removeLast():移除相关元素
removeFirstOccurrence(Object o):移除此双端队列中第一次出现的指定元素
removeLastOccurrence(Object o): 移除此双端队列中最后一次出现的指定元素
-
其他方法:
Iterator descendingIterator():返回以逆向顺序在此双端队列的元素上进行迭代的迭代器。
ArrayDeque 既可以做队列,也可以做堆栈使用。
Stack类
下面介绍Collection接口的两大子接口 List 和 Set
ArrayList类
List接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括null在内的所有元素。除了实现List接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。(此类大致上等同于 Vector
类,除了此类是**不同步**的。)
方法:
-
增加方法:
add() add(int index,E e):将元素e插入到指定位置
addAll(Collection c) addAll(int index,Collection c):将指定collection的元素添加到列表尾
ensureCapacity(int minCapacity):如有必要,增加此
ArrayList实例的容量,以确保它至少能够容纳最小容量参数所指定的元素数。set(int index,E e):用指定的元素替代此列表中指定位置上的元素。
-
获取方法:
get(int index):返回此列表中指定位置上的元素。
indexOf(object o): 返回此列表中首次出现的指定元素的索引,或如果此列表不包含元素,则返回 -1。
lastIndexOf(Object o)返回此列表中最后一次出现的指定元素的索引,或如果此列表不包含索引,则返回 -1。
size():返回此列表中的元素数。
toArray():按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组。
-
删除方法:
clear():移除此列表中的所有元素。
remove(int index):移除此列表中指定位置上的元素。
remove(Object o):移除此列表中首次出现的指定元素(如果存在)。
removeRange(int from,int to):移除列表中索引在
from(包括)和to(不包括)之间的所有元素。 -
其他方法:
contains(Object o):如果此列表中包含指定的元素,则返回
true。isEmpty():如果此列表中没有元素,则返回
truetrimToSize():将此
ArrayList实例的容量调整为列表的当前大小。
LinkedList类
List接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括null)。除了实现List接口外,LinkedList类还为在列表的开头及结尾get、remove和insert元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列。此类实现
Deque接口,为add、poll提供先进先出队列操作,以及其他堆栈和双端队列操作。所有操作都是按照双重链接列表的需要执行的。在列表中编索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。
注意,此实现不是同步的。
方法:
-
增加方法:
add() add(int index,E e):将e插入到指定位置
addAll(Collection c) addAll(int index,Collection c):将指定collection的元素添加到列表尾
addFirst(E e) addLast(E e):将指定元素插入此列表的开头/结尾。
offer(E e):将指定元素添加到此列表的末尾(最后一个元素)。
offerFirst(E e):在此列表的开头插入指定的元素。
offerLast(E e):在此列表末尾插入指定的元素。
push(E e):将元素推入此列表所表示的堆栈。
-
获取方法:
element():获取但不移除此列表的头(第一个元素)。
get(int index):返回此列表中指定位置处的元素。
getFirst() getLast():返回此列表的第一个/最后一个元素。
indexOf(Object o) lastIndexOf(Object o):返回此列表中首次/最后出现的指定元素的索引。
peek():获取但不移除此列表的头(第一个元素)。
peekFirst() peekLast():获取但不移除此列表的第一个/最后一个元素。
poll():获取并移除此列表的头(第一个元素)
pollFirst() pollLast(): 获取并移除此列表的第一个/最后一个元素
-
删除方法:
pop():从此列表所表示的堆栈处弹出一个元素。
remove() remove(int index):获取并移除此列表的头(第一个元素)/ 指定位置元素
remove(Object o):从此列表中移除首次出现的指定元素(如果存在)。
removeFirstOccurrence(Object o):从此列表中移除第一次出现的指定元素(从头部到尾部遍历列表时)
removeFirst() removeLast():移除并返回此列表的第一个/最后一个元素
-
其他方法:
descendingIterator():返回以逆向顺序在此双端队列的元素上进行迭代的迭代器。
toArray():按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组。
LinkedList 和 ArrayDeque都实现了 Deque接口,都能做为堆栈,队列使用。
Vector类
Vector类可以实现可增长的对象数组。与数组一样,它包含可以使用整数索引进行访问的组件。但是,Vector的大小可以根据需要增大或缩小,以适应创建Vector后进行添加或移除项的操作。每个向量会试图通过维护
capacity和capacityIncrement来优化存储管理。capacity始终至少应与向量的大小相等;这个值通常比后者大些,因为随着将组件添加到向量中,其存储将按capacityIncrement的大小增加存储块。应用程序可以在插入大量组件前增加向量的容量;这样就减少了增加的重分配的量。它是线程同步的。
方法:
-
增加方法:
省略基本的add方法
addElement(E e):将指定的组件添加到此向量的末尾,将其大小增加 1。
ensureCapacity(int minCapacity):增加此向量的容量(如有必要),以确保其至少能够保存最小容量参数指定的组件数。
insertElementAt(E e,int index):将指定对象作为此向量中的组件插入到指定的
index处。 -
获取方法:
省略基本的获取方法
elementAt(int index):返回指定索引处的组件。
elements():返回此向量的组件的
枚举。capacity():返回此向量的当前容量。
subList(int from,int to): 返回 List 的部分视图,元素范围为从 from(包括)到 to(不包括)。
toArray():返回一个数组,包含此向量中以恰当顺序存放的所有元素。
-
删除方法:
省略基本的删除方法
removeAllElements():从此向量中移除全部组件,并将其大小设置为零。
retainAll(Collection c):在此向量中仅保留包含在指定 Collection 中的元素。
-
其他方法:
trimToSize():对此向量的容量进行微调,使其等于向量的当前大小。
containsAll(Collection c):如果此向量包含指定 Collection 中的所有元素,则返回 true。
copyInto(Object[] array):将此向量的组件复制到指定的数组中。
toString():返回此向量的字符串表示形式,其中包含每个元素的 String 表示形式。
HashSet类
此类实现
Set接口,由哈希表(实际上是一个HashMap实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用null元素。此类为基本操作提供了稳定性能,这些基本操作包括
add、remove、contains和size,假定哈希函数将这些元素正确地分布在桶中。对此 set 进行迭代所需的时间与HashSet实例的大小(元素的数量)和底层HashMap实例(桶的数量)的“容量”的和成比例。因此,如果迭代性能很重要,则不要将初始容量设置得太高(或将加载因子设置得太低)。注意,此实现不是同步的。
方法:
TreeSet类
基于
TreeMap的NavigableSet实现。使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的Comparator进行排序,具体取决于使用的构造方法。注意,此实现不是同步的。
方法:
-
增加方法:
add(E e):将指定的元素添加到此 set(如果该元素尚未存在于 set 中)。
addAll(Collection c):将指定 collection 中的所有元素添加到此 set 中。
-
获取方法:
first() last():返回此 set 中当前第一个(最低)/最后一个 元素。
ceiling(E e):返回此 set 中大于等于给定元素的最小元素;如果不存在这样的元素,则返回
null。floor(E e):返回此 set 中小于等于给定元素的最大元素;如果不存在这样的元素,则返回
null。higher(E e):返回此 set 中严格大于给定元素的最小元素;如果不存在这样的元素,则返回
null。lower(E e):返回此 set 中严格小于给定元素的最大元素;如果不存在这样的元素,则返回
null。subSet(E from,E to):返回此 set 的部分视图,其元素从
fromElement(包括)到toElement(不包括)。 -
删除方法:
pollFirst():获取并移除第一个(最低)元素;如果此 set 为空,则返回
null。pollLast():获取并移除最后一个(最高)元素;如果此 set 为空,则返回
null。remove(Object o) :将指定的元素从 set 中移除(如果该元素存在于此 set 中)。
-
其他方法:
comparator():返回对此 set 中的元素进行排序的比较器,如果此 set 使用其元素的自然顺序,则返回
null。descendingIterator():返回在此 set 元素上按降序进行迭代的迭代器。
descendingSet():返回此 set 中所包含元素的逆序视图。
headSet(E toElement):返回此 set 的部分视图,其元素严格小于
toElement。tailSet(E from):返回此 set 的部分视图,其元素大于等于
fromElement。
LinkedHashSet类
具有可预知迭代顺序的
Set接口的哈希表和链接列表实现。此实现与HashSet的不同之外在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。注意,插入顺序不 受在 set 中重新插入的 元素的影响。(如果在s.contains(e)返回true后立即调用s.add(e),则元素e会被重新插入到 sets中。)此实现可以让客户免遭未指定的、由
HashSet提供的通常杂乱无章的排序工作,而又不致引起与TreeSet关联的成本增加。使用它可以生成一个与原来顺序相同的 set 副本,并且与原 set 的实现无关此类提供所有可选的
Set操作,并且允许 null 元素。与HashSet一样,它可以为基本操作(add、contains和remove)提供稳定的性能,假定哈希函数将元素正确地分布到存储段中。由于增加了维护链接列表的开支,其性能很可能会比HashSet稍逊一筹,不过,这一点例外:LinkedHashSet迭代所需时间与 set 的大小 成正比,而与容量无关。HashSet迭代很可能支出较大,因为它所需迭代时间与其容量 成正比。链接的哈希 set 有两个影响其性能的参数:初始容量 和 加载因子
注意,此实现不是同步的。
LinkedHashSet 从 Set 接口,HashSet 父类继承大多通用的方法。
Collection接口总结
ArrayDeque 类既可以模拟 队列 也可以模拟 堆栈,因为它不仅扩展了 Queue接口 ,也有模拟堆栈的方法,可以胜于 Stack类 模拟堆栈。它可以支持在集合 头尾增删元素, 获得 元素。
ArrayList 类内部使用变长数组实现,访问指定元素快,但增删比之 LinkedList 慢。
LinkedList 类基于链表实现,同时实现了 Deque 接口,所以和 ArrayDeque 类一样即可模拟队列也能模拟堆栈。当增删元素时效率优于 ArrayList 类,但随即访问元素慢。
Vector 类是线程同步的,而ArrayList 和 LinkedList是线程不同步的。Vector内部和 ArrayList 一样使用变长数组实现。
HashSet 类不保证元素顺序,LinkedSet会使用链表维护集合,TreeSet 实现了 SortedSet,支持自制排序方式。它们都是 线程不同步 的,不支持重复元素。
Set 不支持重复元素,是根据hashCode方法和equals方法来判断的。
注意:
Map/Set的key为自定义对象时,必须重写hashCode和equals。 关于hashCode和equals的处理,遵循如下规则:
1) 只要重写equals,就必须重写hashCode。
2) 因为Set存储的是不重复的对象,依据hashCode和equals进行判断,所以Set存储的对象必须重写这两个方法。
3) 如果自定义对象做为Map的键,那么必须重写hashCode和equals。
Map接口
将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。
此接口取代
Dictionary类,后者完全是一个抽象类,而不是一个接口。
Map接口提供三种collection 视图,允许以键集、值集或键-值映射关系集的形式查看某个映射的内容。映射顺序 定义为迭代器在映射的 collection 视图上返回其元素的顺序。某些映射实现可明确保证其顺序,如TreeMap类;另一些映射实现则不保证顺序,如HashMap类。
介绍一下 Map 接口的常用实现类
HashMap类
基于哈希表的
Map接口的实现。此实现提供所有可选的映射操作,并允许使用null值和null
键。(除了非同步和允许使用 null 之外,HashMap类与Hashtable大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。此实现假定哈希函数将元素适当地分布在各桶之间,可为基本操作(
get和put)提供稳定的性能。迭代 collection 视图所需的时间与HashMap实例的“容量”(桶的数量)及其大小(键-值映射关系数)成比例。所以,如果迭代性能很重要,则不要将初始容量设置得太高(或将加载因子设置得太低)。
HashMap的实例有两个参数影响其性能:初始容量 和加载因子。注意,此实现不是同步的。
方法:
包含基本的 增加映射 删除映射 获取值 返回键的Set集合 返回值的Collectiion集合等方法
LinkedHashMap类
LinkedHashMap 继承 HashMap
Map接口的哈希表和链接列表实现,具有可预知的迭代顺序。此实现与HashMap的不同之处在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序通常就是将键插入到映射中的顺序(插入顺序)。注意,如果在映射中重新插入 键,则插入顺序不受影响。(如果在调用m.put(k, v)前m.containsKey(k)返回了true,则调用时会将键k重新插入到映射m中。)由于增加了维护链接列表的开支,其性能很可能比
HashMap稍逊一筹,不过这一点例外:LinkedHashMap的 collection 视图迭代所需时间与映射的大小 成比例。HashMap迭代时间很可能开支较大,因为它所需要的时间与其容量 成比例。注意,此实现不是同步的。
LinkedHashMap 的方法大多继承自 HashMap
TreeMap类
基于
红黑树(Red-Black tree)的NavigableMap实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的Comparator进行排序,具体取决于使用的构造方法。此实现为
containsKey、get、put和remove操作提供受保证的 log(n) 时间开销。注意,此实现不是同步的。
TreeMap类 提供了大多是对于键值对排序序列相关的方法。
HashTable类
此类实现一个哈希表,该哈希表将键映射到相应的值。任何非
null对象都可以用作键或值。为了成功地在哈希表中存储和获取对象,用作键的对象必须实现
hashCode方法和equals方法。
Hashtable的实例有两个参数影响其性能:初始容量 和加载因子。
方法:
继承 Map 基本方法
elements():返回此哈希表中的值的枚举
keys():返回此哈希表中的键的枚举
toString():返回此 Hashtable 对象的字符串表示形式
Properties类
Properties类 继承自 HashTable类
Properties类表示了一个持久的属性集。Properties可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。一个属性列表可包含另一个属性列表作为它的“默认值”;如果未能在原有的属性列表中搜索到属性键,则搜索第二个属性列表。
因为
Properties继承于Hashtable,所以可对Properties对象应用put和putAll方法。但不建议使用这两个方法,因为它们允许调用者插入其键或值不是String的项。相反,应该使用setProperty方法。此类是线程同步的
方法:
setProperty(String key,String value):调用 Hashtable 的方法 put。
getProperty(String key):用指定的键在此属性列表中搜索属性。
list(PrintWriter out) list(PrintStream out):将属性列表输出到指定的输出流。
load(inputStream in):从输入流中读取属性列表(键和元素对)。
load(Reader reader) :按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。
store(OutputStream out,String comments):将此 Properties 表中的属性列表(键和元素对)写入输出流
store(Writer writer,String comments):将此 Properties 表中的属性列表(键和元素对)写入输出字符流。
stringPropertyNames():返回此属性列表中的Set 键集,其中该键及其对应值是字符串
Map接口总结
基于哈希表的 Map 接口实现。除了未实现同步并允许 null 值,HashMap 和 HashTable 大致一样,不过 HashTable 基本上已经废弃了,如果需要同步,可以使用 CurrentHashMap 作为更好的代替。
LinkedHashMap 它比 HashMap 多维护了一个双向链表,因此可以按照插入的顺序从头部或者从尾部迭代,是有序的。插入元素比HashMap快。
TreeMap 的底层是一颗红黑树,它的 containsKey , get , put and remove 方法的时间复杂度是 log(n) 。