Java基础知识点3:集合类

集合类是Java编程中经常会用到的一类常用类库,在这里将会对整个集合类进行介绍:

Collection接口:

  Collection接口是所有集合类的根接口,代表了所有含有多个元素的集合,无论这个集合中是否有重复元素,元素是否有序。所有我们经常使用的一些集合类,比如ArrayList,LinkedList等等集合类并不是直接实现这个接口。而是去实现这个Collection接口的子接口,比如Set,List等等。

  这个类中规定了一些最通用的方法,比如:

  size(), isEmpty(),contains(Object o), iterator(),toArray(),add(E e), remove(Object o),containsAll(Collection<?> c), addAll(Collection<? extends E> c),removeAll(Collection<?> c),retainAll(Collection<?> c),clear(),equals(Collection<?> c),hashCode();

  但是仅仅声明这个接口其实还不够方便,因为Java语法规定接口中只会对方法进行声明,不会有具体的实现,所以如果想要创建两个不同的,但是都能实现Collection接口的集合类,比如ArrayList和LinkedList,就需要在它们各自类声明文件中去重复实现像isEmpty(),contains()这样的通用方法。比如关于isEmpty()方法的具体实现,我们需要在这个两个类中都分别都列出size()方法的代码,这是一个非常麻烦的操作。

AbstractCollection抽象类

  所以为了解决这个问题,java中定义了一个实现Collection接口的抽象类AbstractCollection,这个类中对于一些简单的通用方法进行的了实现,比如contains()等等。通过这个方案,如果程序员再想要定义一个新的集合类,只需定义一个继承自AbstractCollection类的子类即可,这样就免去了还要重新写一遍contains()等方法的代码的麻烦。

List接口:

  List接口是继承自Collection接口的一个子接口。实现这个接口的集合类代表一个有序集合(也可以把它叫作序列)。也就是说这种集合类可以允许用户通过元素的位置序号来访问,修改这个元素。实现List接口的集合类通常可以包含重复元素。

  所以相比于Collection接口,List接口会定义一些额外的,和元素位置有关的操作,比如

  get(int index):获取位于第index位置处的元素,除此之外还有set(int index, E element),add(int index, E element),remove(int index),indexOf,lastIndexOf,subList(int fromIndex, int toIndex),listIterator(),listIterator(int index)

AbstractList抽象类

  和Collection接口定义AbstractCollection抽象类的目的类似,java针对List接口也定义了一个抽象类AbstractList,其中实现了很多重要的公共方法,比如indexOf,lastIndexOf等等。但是下面的几个方法没有具体实现,需要在具体的集合类中来实现它们:

  get(int index),set(int index, E element),add(int index, E element),remove(int index)

AbstractSequentialList抽象类

  按照这个类的声明文件中所叙述的,这个抽象类的作用是为了帮助我们实现顺序存储的数据结构而提供的抽象类。在这个类中实现了get,set,add,remove方法,不过采取的实现方式和ArrayList不同,是通过listIterator这个数据结构来实现的。

ArrayList类

  这个集合类继承自AbstractList抽象类,它的实现机制就像它的名字中所写的那样,是通过数组Array来实现的一个List结构。在ArrayList中包含一个Object数组,elementData,存放所有数组元素,和另一个size变量,存放当前数组中元素的个数。

  在这个类中实现了几个比较重要的方法,get,set,add,remove。除此之外还重新实现了一些其他的方法,如indexOf,lastIndexOf等等。

LinkedList类

  这个集合类继承子AbstractSequentialList抽象类,实现的是一种顺序访问的线性表结构,和ArrayList的区别就在于,它不能以常数时间复杂度O(1)访问线性表中的任意一个元素,只能顺序访问。这个集合类是通过双链表来实现的。类中一共包含两个成员

变量:一个是双链表的头结点指针Entry<E> header;另一个是该双链表的元素个数,size。

  由于LinkedList实现了List,Deque接口,所以LinkedList声明文件中包含了比ArrayList更多的方法,主要来自于Deque接口。

  在LinkedList中一些基本操作都是基于双链表来实现的,时间复杂度如下:

  add(E e)复杂度O(1)。remove(Object o)复杂度O(n)。get(int index)复杂度O(n)。set(int index, E element)复杂度O(n)。remove(int index)复杂度O(n)。其他的方法都是基于这几个方法的。

Vector类

  Vector类的实现方式和ArrayList很像,因为这两个集合类都是模拟一种可以在常数时间复杂度进行随机访问的数据结构。所以它也是采用数组来实现的。

     

Set接口:

  Set接口也是继承自Collection的另一个子接口。实现这个接口的集合类代表一个不包含重复元素的集合。也就是说任何在同一个Set中的两个元素e1,e2,e1.equals(e2)=false。而且集合中至多只有一个null元素。

  相比于Collection接口,Set接口并没有定义新的方法。但是要保证从Collection继承的方法能够在保证集合中不包含重复元素的前提下完成各项操作。

AbstractSet抽象类:

  就像List接口要实现一个AbstractList抽象类来方便我们具体的某个List集合类的构造,比如ArrayList,Set接口也有一个AbstractSet抽象类,里面定义了一些Set接口中声明的方法,因为这些方法在不同的具体的Set集合类中实现方式都是一样的。比如hashCode方法在HashSet和TreeSet方法中是一样的。

HashSet类:

  这个类是通过哈希表来实现的Set集合类。它有以下几个特点:

  1. 在遍历整个集合中的元素时,它不能保证元素出现的次序,即元素之间没有严格的次序关系。

  2. 这个类支持常数时间复杂度的基本操作,比如add,remove,contains,size。

  3. 遍历整个hashSet中的元素所需要时间与HashSet中的元素个数以及实现这个HashSet的HashMap的大小之和成正比。

  

  HashSet是基于HashMap实现的,即在HashSet中定义了一个HashMap,不过这个HashMap的每一个键值对中,键的类型由程序动态给定,值的类型则是固定的Object类型。

  通过观察HashSet的源代码发现,由于HashSet是通过一个HashMap来实现的。所以HashSet中的很多方法也是通过调用HashMap中的已有方法来实现的。比如contains方法:

  public boolean contains(Object o) {

    return map.containsKey(o);

  }

Map接口:

  这个接口所代表的数据结构是能够存放键值对(key/value)的集合,它有以下几个特点:

  1. 同一个集合中,关键字(key)不能重复。

  2. 每一个关键字(key)至多只能映射到一个值上。

  这个接口中声明了关于键值对集合的一些通用操作。

AbstractMap抽象类:

  

原文地址:https://www.cnblogs.com/fatsheep9146/p/5183639.html