目录
文章目录
集合框架综述
一、简介
官方教程: Collections
Java集合框架(Java Collection Framework),又被称为集合容器(Collection Container),是定义在java.util包下的一组接口(Interfaces)和其实现类(Classes)。其主要表现为将多个对象元素置于一个容器中,用于对这些对象元素进行快速、便捷的存储(Store)、检索(Retrieve)和管理(Manipulate)。
Java集合框架的设计是为了满足数据的更多逻辑关系,提供一系列不同于数组的可变的聚合的抽象数据类型。帮助解决了数组使用过程中的各种痛点:
- 数组在内存存储方面:
- 数组初始化以后,长度就确定不变;
- 数组声明的类型,就决定了进行元素初始化时的类型。
- 数组在存储数据方面:
- 数组初始化以后,长度就不可变,不便于扩展;
- 数组中提供的属性和方法少,不便于进行增、删等操作,且效率不高。同时无法直接获取存储元素的个数;
- 数组存储的数据是有序的、可以重复的,并且存储数据的特点单一;
- 数组中存储的是同一类型的元素,可以存储基本数据类型值。而集合存储的都是对象,而且对象的类型可以不一致。
二、框架图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CKVNqisk-1625502263349)(en-resource://database/4155:1)]
从Java 集合框架图可以了解到一下两点
-
Java集合框架主要包括两种类型的容器
- 一种是集合(Collection),存储一组元素;
- List:元素有序,可重复;
- Set:元素无序,不可重复。
- 一种是图(Map),存储键/值对映射。
- 一种是集合(Collection),存储一组元素;
-
Java集合框架上来看,其围绕一组标准接口而设计并提供对外扩展,具有高性能、高效等特点,并允许不同类型的集合,以相似的方式来操作。包括三个部分
- 接口:代表集合的抽象数据类型,如Iterator、Collection、List、Set、Map等;
- 实现(类):是接口的具体实现,如ArrayList、HashSet、HashMap等;
- 算法:是使用实现集合接口的对象里面的方法执行一些计算,如排序、检索等。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hNKAGppr-1625502263352)(en-resource://database/4131:1)]
三、重要接口和实现类
3.1 Collection接口
官方教程:Collection
Collection接口是集合类的根接口,它包含了集合的基本操作和属性。Java中没有提供这个接口的直接的实现类。但是却让其被继承产生了三个主要个接口:List、Set和Queue。
3.1.1 List
List是一个有序(插入顺序)的集合,可以包含重复的元素,提供了按索引访问的方式。List允许null值存在,但仅有一个。
List接口实现主要有以下几种类型:
- ArrayList:底层是由数组实现,可以看成是一个动态数组。ArrayList擅长随机访问。但在中间插入、移除元素时代价较高;
在使用中需要注意:在明确所要存储的元素个数的情况下,最好指定初始容量值,避免过多的进行扩容操作而浪费时间、影响效率; - LinkedList:底层由双向链表实现,可以看成是一个双向链表。由于实现方式的不同,LinkedList不能随机访问,它所有操作都要按照双重链表的需要执行,在列表中索引的操作将从开头或结尾遍历,这样在List中间插入和移除元素时代价较低。
- Vertor:与ArrayList相似,但Vector是同步的,所以说Vector是现场安全的动态数组;
- Stack:继承至Vector,实现了一个先进后出的堆栈。
3.1.2 Set
Set是一个无序的集合,不能包含重复的元素。它和Collection完全一样的接口,没有额外的功能提供。它维护了自己的内部排序(hashCode决定元素的具体位置),所以随机访问并没有任何意义。它同样和List一样,允许null值,但仅有一个。
Set接口实现主要有以下几种类型:
- HashSet:无序不重复元素集合,是由HashMap实现的,不保证元素的顺序。HashSet是按Hash算法来存储元素,因此具有良好的存储和查找性能。HashSet的实现是通过一个HashMap存储元素,元素是存放在HashMap的Key中,而Value统一使用一个Onject对象。
- LinkedHashSet:继承自HashSet,其底层是基于LinkedHashMap实现的。LinkedHashSet集合同样是根据元素的hashCode值来决定元素的存储位置,但是它同时使用链表维护元素的次序。
- TreeSet:有序(采用红黑树存储)不重复实现,查找速度不如HashSet快。TreeSet底层是基于TreeMap实现的。TreeSet支持两种排序方式:自然排序和定制排序,默认是自然排序。
3.1.3 Queue
Queue(队列)是一种较为特殊的线性表,它是典型的先进先出(FIFO)的容器。
新元素插入(offer)到队列的尾部,访问元素(poll)操作会返回队列头部的元素。通常,队列不允许随机访问队列中的元素。
Queue有一个Deque子接口,这是一个双端队列,先元素插入既可以在头部,又可以在尾部,访问元素也是一样,可以在头部,也可以在尾部。
Deque 实现类有 LinkedList、 ArrayDeque、ConcurrentLinkedDeque 等等。
3.2 Map接口
官方教程:Map
Map是java.util包中的另外一个接口,它和Collection接口没有关系,是相互独立的,但是都属于集合类的一部分。
Map数据结构是用于保存具有映射关系的键值对数据(Key, Value),即Map集合保存着两组值,一组用于保存Map里面的key,另一组用于保存Map里面的value,且key和value可以是任何引用类型的数据。
Map中key不可重复,即一个Map对象中的任何两个key通过equals方法比较返回的总数false。key和value是一对一关系,即通过指定的key可以确定唯一与其对应的value。
Map接口的实现有很多,根据特性的不同,效率的高低,保存的形式及多线程方面的考虑,分为了多种实现方式,包括:
- HashMap:基于哈希表数据结构的实现,插入和查询键值对的开销是固定的,可以通过构造器设置容量和负载因子。HashMap是为了快速查询而设计的,其内部定义了一个hash表数组(Node<K,V>[] table),元素通过哈希转换函数将元素的哈希地址转换成数组中存放的索引,若出现冲突,则以散列链表的形式将元素串联起来。
- LinkedHashMap:是HashMap的一个子类,但是其使用链表维护内部次序(插入次序),因此,在迭代访问时速度快;
- TreeMap:基于红黑树的实现,TreeMap存储时会进行排序的,会根据key来对key-value键值对进行排序,其中排序方式也是分为两种:自然排序和定制排序,具体取决于使用的构造方法。其判定key重复的方法并不是equals()方法而是:两个key通过compareTo()方法返回0,则认为这两个key相等。
- ConcurrentHashMap:线程安全的Map,不涉及同步加锁;
- WeakHashMap:弱键映射,允许释放映射所指向的对象,专为解决特殊问题而设计;
- IdentityHashMap:使用==代提equals()对键进行比较的散列映射,专为解决特殊问题而设计。
3.3 Iterator接口
Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法,可用于迭代集合。
迭代器是一种轻量化的对象,创建它的代价非常小,但是也正是因为其创建代价小,而使得其限制多。例如,只能单向移动,使用next()获得序列中的下一个元素,使用hasNext()检查序列中是否还有元素,使用remove()将迭代器新近返回的元素删除。
使用迭代器来遍历集合,是真正的统一了对集合的访问方式,因为它遍历集合的操作与集合底层的结构做到了分离。
3.4 ListIterator接口
ListIterator是一个功能更加强大的迭代器, 它继承于Iterator接口,只能用于各种List类型的访问。可以通过调用listIterator()方法产生一个指向List开始处的ListIterator, 还可以调用listIterator(n)方法创建一个一开始就指向列表索引为n的元素处的ListIterator。
Iterator和ListIterator区别
- ListIterator有add()方法,可以向List中添加对象,而Iterator不能
- ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。
- ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。
- 都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可以实现。Iierator仅能遍历,不能修改。
3.5 RandomAccess接口
这个接口不包含任何方法,只是用来测试一个特定的集合是否支持高校的随机访问。