Java集合整体框架及Collection

目录
导读
(一)java集合框架
1.1接口与实现分离
1.2Collection接口
1.2.1定义
1.3迭代器
1.4泛型
(二)图解Java集合框架
2.1整体架构

(三)Collection结构

3.1Collection vs Collections

3.2Collection的子接口

3.3List

3.4Set

3.5AbstractCollection

3.6AbstractList

3.7AbstractSet

3.8Iterator

3.9ListIterator

(四)Map结

4.1Map结构图

(五)总结


导读
Java集合是java提供的工具包,包含了常用的数据结构:集合、链表、队列、栈、数组、映射等。Java集合工具包位置是java.util.*
Java集合主要可以划分为4个部分:List列表、Set集合、Map映射、工具类(Iterator迭代器、Enumeration枚举类、Arrays和Collections)。
在这篇文章中,对Java中的集合部分进行了整体型的概述,以及对于Collection进行了较为详细的解释,其中各个分支实现类的讲解,之后将逐渐进行整理。
(一)java集合框架
1.1 接口与实现分离
Java集合 类库将接口与实现分离,一旦构建了集合就不需要知道究竟使用了哪种实现,所以,只有在构建集合对象时,使用具体的类才有意义。可以使用接口类型存放集合的引用,这样的话,一旦改变了想法,可以轻松使用另外一种不同的实现,只需要对程序 的一处进行修改,即调用构造器的地方。比如,对于大家熟悉的一种数据结构队列,在java集合中队列的接口表示为Queue<E>,它的实现方式有两种,数组队列和链表队列,也就是对应着ArrayQueue()和LinkedListQueue(),假如在之前的程序中,使用了
Queue<Student> test = new ArrayQueue<>();
test.add(new Student);
...
但是现在因为某些原因需要使用LinkedListQueue();那么就只需要将代码修改为
Queue<Student> test = new LinkedListQueue<>();
test.add(new Student);
...
至于为什么选择这种实现而不选择另外一种实现,接口本身并不能说明哪种实现的效率怎么样。仍旧拿队列的例子来说,循环数组比链表效率高,所以大部分情况下优先选择循环数组,也就是ArrayQueue来实现,但是这样做也是要付出一定的代价的,因为数组是一个有界集合,所以如果程序中收集的对象没有上限,那么最好使用LinkedList()来实现。
在这里提前说明一点,如果你研究过Java的API文档,你会发现一组以Abstract开头的类,比如队列对应着AbstractQueue。具有这个名称特征的类是为类库实现者而设计的,如果你需要自己的队列类,而不使用ArrayQueue或者LinkedList这样的实现类(一般不太可能,这里只是强调“Abstract”类的作用),你会发现扩展Abstract类要比实现Queue接口中的所有方法轻松很多。
1.2 Collection接口
1.2.1定义
在Java类库中,集合类的基本接口时Collection接口,其中有·两个基本方法,
abstract boolean         add(E object)
abstract Iterator<E>     iterator()  	


当然远不止这两个方法,作为引出这个集合的基本接口,简单介绍一下这两个方法。

add()方法用于向集合 中添加元素。例如,现在试图向集合中添加一个对象,而这个对象已经存在,那么add方法就返回false,因为集中不允许有重复的对象;
iterator方法用于返回一个实现Iterator接口的对象,然后使用这个迭代器对象可以依次访问结合中的元素,关于迭代器,后面会扩展讲到。

现在我们更详细地去理解一下Collection接口。

Collection是一个接口,是高度抽象出来的集合,它包含了集合的基本操作和属性:加、删除、清空、遍历(读取)、是否为空、获取大小、是否保护某元素等等。

Collection接口的所有子类(直接子类和间接子类)都必须实现2种构造函数:不带参数的构造函数 和 参数为Collection的构造函数。带参数的构造函数,可以用来转换Collection的类型。

下面是Collection的API
// Collection的API
abstract boolean         add(E object)
abstract boolean         addAll(Collection<? extends E> collection)
abstract void            clear()
abstract boolean         contains(Object object)
abstract boolean         containsAll(Collection<?> collection)
abstract boolean         equals(Object object)
abstract int             hashCode()
abstract boolean         isEmpty()
abstract Iterator<E>     iterator()
abstract boolean         remove(Object object)
abstract boolean         removeAll(Collection<?> collection)
abstract boolean         retainAll(Collection<?> collection)
abstract int             size()
abstract <T> T[]         toArray(T[] array)
abstract Object[]        toArray()
再来说Collection是个什么东西
Collection包含了List和Set两大分支。
(01) List是一个有序的队列,每一个元素都有它的索引。第一个元素的索引值是0。

List的实现类有LinkedList, ArrayList, Vector, Stack。

(02) Set是一个不允许有重复元素的集合。

Set的实现类有HastSet和TreeSet。HashSet依赖于HashMap,它实际上是通过HashMap实现的;TreeSet依赖于TreeMap,它实际上是通过TreeMap实现的。

是不是有很多陌生的类不知道是什么,没关系,第二章节会详细地说明他们和Collection之间的关系。

1.3迭代器
上文中提到过这个概念,就是Iterator。Iterator接口包含了四个方法:
public interface Iterator<E>{
	E next();
	boolean hasNext();
	void remove();
	default void forEachRemaining(Consumer<? super E> action);}
通过反复调用next方法,可以逐个访问集合中的每个元素。但是,如果达到了集合的末尾,next将会抛出NoSuchElementException。所以在调用next之前要用hasNext。
Collection<String> c = ...;
	Iterator<String> iter = c.iterator();
	while(iter.hasNext){
		String element = iter.next();
		do something with element...
}
当然,现在主流的方法更多的是使用foreach循环遍历集合
for(String element : c){
	do something with element...
}
Java8之后可以调用forEachRemaining方法并提供一个lambda表达式,将对迭代器的每一个元素调用这个lambda表达式,直到再没有元素为止。
interator.forEachRemaining(element->do something with element..);
元素的访问顺序取决于集合类行,ArrayList的迭代过程将从索引0开始,每迭代一次,索引值加1.但是对于Hash来说,每个元素将会按照某种随机的次序出现。对于迭代器,还有一点需要特别注意,迭代器是位于两个元素之间,如果不好理解,可以把它想象成光标,当调用next时,迭代器就越过一个元素,并返回刚刚越过的元素的引用。关于迭代器会另起文章详细解释。
1.4 泛型
由于Collection与Iterator都是泛型接口,可以编写操作任何集合类行的实用方法。
在之前的API介绍中,可以看出接口中很多方法非常明确,无需过多解释,但是如果实现Colection接口的每一个类都要提供如此多的例行方法将会非常麻烦,这就和之前说有一些Abstract模样的类,java提供了一个类AbstractCollevtion,如果此时一个具体的集合类就可以扩展AbstractCollection。
(二)图解Java集合框架
2.1 总体架构
Java集合主要可以划分为4个部分:List列表、Set集合、Map映射、工具类(Iterator迭代器、Enumeration枚举类、Arrays和Collections)。
Java集合工具包框架图(如下):

看上面的框架图,先抓住它的主干,即Collection和Map。
1 Collection是一个接口,是高度抽象出来的集合,它包含了集合的基本操作和属性。
Collection包含了List和Set两大分支。
(01) List是一个有序的队列,每一个元素都有它的索引。第一个元素的索引值是0。
List的实现类有LinkedList, ArrayList, Vector, Stack。
(02) Set是一个不允许有重复元素的集合。
 Set的实现类有HastSet和TreeSet。HashSet依赖于HashMap,它实际上是通过HashMap实现的;TreeSet依赖于TreeMap,它实际上是通过TreeMap实现的。
(03) Queue队列又称为“先进先出”(FIFO—first in first out)的线性表。
 LinkedList类实现了Queue接口,因此我们可以把LinkedList当成Queue来用。另外ArrayDeque也是实现类之一。
 
2 Map是一个映射接口,即key-value键值对。Map中的每一个元素包含“一个key”和“key对应的value”。
AbstractMap是个抽象类,它实现了Map接口中的大部分API。而HashMap,TreeMap,WeakHashMap都是继承于AbstractMap。
Hashtable虽然继承于Dictionary,但它实现了Map接口。

接下来,再看Iterator。它是遍历集合的工具,即我们通常通过Iterator迭代器来遍历集合。我们说Collection依赖于Iterator,是因为Collection的实现类都要实现

iterator()函数,返回一个Iterator对象。ListIterator是专门为遍历List而存在的。

再看Enumeration,它是JDK 1.0引入的抽象类。作用和Iterator一样,也是遍历集合;但是Enumeration的功能要比Iterator少。在上面的框图中,Enumeration只能在Hashtable, Vector, Stack中使用。
最后,看Arrays和Collections。它们是操作数组、集合的两个工具类。

(三)Collection结构


3.1 Collection vs Collections
Collection是个java.util下的接口,它是各种集合结构的父接口。
Collections是个java.util下的类,它包含有各种有关集合操作的静态方法。

Collection 层次结构中的根接口。Collection 表示一组对象,这些对象也称为 Collection的元素。一些 Collection 允许有重复的元素,而另一些则不允许。一些 Collection 是有序的,而另一些则是无序的。JDK 不提供此接口的任何直接 实现:它提供更具体的子接口(如 Set 和 List)实现。此接口通常用来传递 collection,并在需要最大普遍性的地方操作这些 Collection。
Collections 此类完全由在 Collection 上进行操作或返回 Collection 的静态方法组成。它包含在 Collection 上操作的多态算法,即“包装器”,包装器返回由指定 Collection 支持的新 Collection,以及少数其他内容。 如果为此类的方法所提供的 Collection 或类对象为 null,则这些方法都会抛出 NullPointerException。

3.2 Collection的子接口



3.3 List
List的定义如下:
public interface List<E> extends Collection<E> {}

List是一个继承于Collection的接口,即List是集合中的一种。List是有序的队列,List中的每一个元素都有一个索引;第一个元素的索引值是0,往后的元素的索引值依次+1。和Set不同,List中允许有重复的元素。
List的官方介绍如下:
A List is a collection which maintains an ordering for its elements. Every element in the List has an index. Each element can thus be accessed by its index, with the first index being zero. Normally, Lists allow duplicate elements, as compared to Sets, where elements have to be unique. 
关于API方面。既然List是继承于Collection接口,它自然就包含了Collection中的全部函数接口;由于List是有序队列,它也额外的有自己的API接口。主要有“添加、删除、获取、修改指定位置的元素”、“获取List中的子队列”等。
// Collection的API
abstract boolean         add(E object)
abstract boolean         addAll(Collection<? extends E> collection)
abstract void            clear()
abstract boolean         contains(Object object)
abstract boolean         containsAll(Collection<?> collection)
abstract boolean         equals(Object object)
abstract int             hashCode()
abstract boolean         isEmpty()
abstract Iterator<E>     iterator()
abstract boolean         remove(Object object)
abstract boolean         removeAll(Collection<?> collection)
abstract boolean         retainAll(Collection<?> collection)
abstract int             size()
abstract <T> T[]         toArray(T[] array)
abstract Object[]        toArray()
// 相比与Collection,List新增的API:
abstract void                add(int location, E object)
abstract boolean             addAll(int location, Collection<? extends E> collection)
abstract E                   get(int location)
abstract int                 indexOf(Object object)
abstract int                 lastIndexOf(Object object)
abstract ListIterator<E>     listIterator(int location)
abstract ListIterator<E>     listIterator()
abstract E                   remove(int location)
abstract E                   set(int location, E object)
abstract List<E>             subList(int start, int end)
3.4 Set
Set的定义如下:
public interface Set<E> extends Collection<E> {}

Set是一个继承于Collection的接口,即Set也是集合中的一种。Set是没有重复元素的集合。

关于API方面。Set的API和Collection完全一样。
// Set的API
abstract boolean         add(E object)
abstract boolean         addAll(Collection<? extends E> collection)
abstract void             clear()
abstract boolean         contains(Object object)
abstract boolean         containsAll(Collection<?> collection)
abstract boolean         equals(Object object)
abstract int             hashCode()
abstract boolean         isEmpty()
abstract Iterator<E>     iterator()
abstract boolean         remove(Object object)
abstract boolean         removeAll(Collection<?> collection)
abstract boolean         retainAll(Collection<?> collection)
abstract int             size()
abstract <T> T[]         toArray(T[] array)
abstract Object[]         toArray()
3.5 AbstractCollection
AbstractCollection的定义如下:
public abstract class AbstractCollection<E> implements Collection<E> {}
AbstractCollection是一个抽象类,它实现了Collection中除iterator()和size()之外的函数。
AbstractCollection的主要作用:它实现了Collection接口中的大部分函数。从而方便其它类实现Collection,比如ArrayList、LinkedList等,它们这些类想要实现Collection接口,通过继承AbstractCollection就已经实现了大部分的接口了。

3.6 AbstractList
AbstractList的定义如下:
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {}
AbstractList是一个继承于AbstractCollection,并且实现List接口的抽象类。它实现了List中除size()、get(int location)之外的函数。
AbstractList的主要作用:它实现了List接口中的大部分函数。从而方便其它类继承List。
另外,和AbstractCollection相比,AbstractList抽象类中,实现了iterator()接口。

3.7 AbstractSet
AbstractSet的定义如下: 
public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E> {}
AbstractSet是一个继承于AbstractCollection,并且实现Set接口的抽象类。由于Set接口和Collection接口中的API完全一样,Set也就没有自己单独的API。和AbstractCollection一样,它实现了List中除iterator()和size()之外的函数。
AbstractSet的主要作用:它实现了Set接口中的大部分函数。从而方便其它类实现Set接口。

3.8 Iterator
Iterator的定义如下:
public interface Iterator<E> {}
Iterator是一个接口,它是集合的迭代器。集合可以通过Iterator去遍历集合中的元素。Iterator提供的API接口,包括:是否存在下一个元素、获取下一个元素、删除当前元素。
注意:Iterator遍历Collection时,是fail-fast机制的。即,当某一个线程A通过iterator去遍历某集合的过程中,若该集合的内容被其他线程所改变了;那么线程A访问集合时,就会抛出ConcurrentModificationException异常,产生fail-fast事件。关于fail-fast的详细内容,我们会在后面专门进行说明。
// Iterator的API
abstract boolean hasNext()
abstract E next()
abstract void remove()

3.9 ListIterator
ListIterator的定义如下:
public interface ListIterator<E> extends Iterator<E> {}
ListIterator是一个继承于Iterator的接口,它是队列迭代器。专门用于便利List,能提供向前/向后遍历。相比于Iterator,它新增了添加、是否存在上一个元素、获取上一个元素等等API接口。
// ListIterator的API
// 继承于Iterator的接口
abstract boolean hasNext()
abstract E next()
abstract void remove()
// 新增API接口
abstract void add(E object)
abstract boolean hasPrevious()
abstract int nextIndex()
abstract E previous()
abstract int previousIndex()
abstract void set(E object)



(四)Map结构

4.1 Map结构图


Map是一种映射,这一部分其实是和Collection并列的一部分,内容非常多而重要,它的继承结构基本和Collection类似,关于HashMap博客中已经存在两篇文章进行了详细的解释,其他的实现类,今后一一整理。


(五)总结

总结一下接口 和实现类的关系吧


猜你喜欢

转载自blog.csdn.net/adelaide_guo/article/details/78577985