java Conllection接口及其实现类

Java集合大致可分为Set、List和Map三种体系,其中Set代表无序、不可重复的集合;List代表有序、重复的集合;
而Map则代表具有映射关系的集合。Java 5之后,增加了Queue体系集合,代表一种队列集合实现。Java集合框架主要由Collection和Map两个根接口及其子接口、实现类组成。


Collection接口
接口是Set、List和Queue接口的父接口,方法有
  • add(Object o):添加元素
  • addAll(Collection c):添加c集合中所有元素
  • clear():删除Collection对象中的所有元素
  • contains(Object o):是否包含o元素,底层调用为equals()方法
  • containsAll(Collection c):是否包含集合c中的所有元素
  • iterator():返回Iterator对象,用于遍历集合中的元素
  • remove(Object o):移除元素
  • removeAll(Collection c):从集合中移出它和C对象相同的元素。而对于A中含有而B中不含有的对象,不移除。
  • retainAll(Collection c):相当于求与c的交集
  • size():返回元素个数
  • toArray():把集合转换为一个数组
  • hashCode():返回字符串的哈希码。
Collection接口中并未重写toString(),toString的重写是在它的实现类AbstractCollection中实现的。

Set子接口

Set接口是Collection接口的子类,其继承了所有方法,HashSet集合则实现了Set接口,其内部存储数据时依靠哈希表,一个类似数组和链表的结合体。设置空集合时,存在默认的容量和加载因子,再用HashSet对象调用add方法时,其实是先比较其Hash值,若是没有的话,则直接添加到集合中,若有的话,则再equals下比较其内容(因为有可能内容不一样,但是其Hash值一样),若是内容不一样,则在这个地址下添加(链式),若是一样的话,则丢掉。注意就保证了其的唯一性。(以后定义变量时,都需要重写其hashcode和equals方法)至于LinkedHashSet则在HashSet基础上保证了其的有序性(取出和存入顺序一样)。

HashSet

 由HashSet的源码可知,HashSet底层就是一个HashMap。我们在往HashSet中存储数据的时候,HashSet添加的元素是存放在HashMap的key位置上,而value取了默认常量PRESENT,是一个空对象。
 HashSet底层的数据结构是一个哈希表,存在HashSet中的元素应该重写其hashCode()方法,故存在HashMap中的key,应该 重写其hashCode()方法。HashSet集合不能保证迭代顺序与元素的存储顺序相同。

扩容机制:默认初始容量为16。加载因子为0.75:即当 元素个数 超过 容量长度的0.75倍 时,进行扩容。扩容增量:原容量的 1 倍

LinkedHashSet类

LinkedHashSet具有set集合不重复的特点,同时具有可预测的迭代顺序,也就是我们插入的顺序。因为是HashSet的子类,所以也是保证元素唯一的,与HashSet的原理一样。

此实现与 HashSet 的不同之处在于,LinkedHashSet 维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序可为插入顺序或是访问顺序。

SortSet接口与TreeSet类

TreeSet为SortSet的一个实现类,该类可以按照元素大小进行排序,但是存入的对象必须实现Comparable<T>接口并对其比较方法进行重写,可以比较出对象比较后的大小。或者使用java.util.Comparator;来单独编写一个比较器,创建TreeSet集合的时候提供这个比较器,如果未实现接口或提供比较器会抛出ClassCastException。

新增方法:

  1. first():返回第一个元素
  2. last():返回最后一个元素
  3. lower(Object o):返回指定元素之前的元素
  4. higher(Obect o):返回指定元素之后的元素
  5. subSet(fromElement, toElement):返回子集合

EnumSet类

EnumSet这是一个用来操作Enum的集合,EnumSet中的所有元素都必须是指定枚举类型的枚举值,它是一个抽象类,有两个继承类:JumboEnumSet和RegularEnumSet。在使用的时候,需要确定枚举类型。它的特点也是速度非常快。
EnumSet是一个抽象类,不能直接通过new新建,noneOf方法会创建一个指定枚举类型的EnumSet,不含任何元素。创建的EnumSet对象的实际类型是EnumSet的子类,线程不安全

List接口

List子接口是有序集合。有索引,包含了一些带索引的方法,还允许存储重复的元素。

void add(int index, E element) 在指定 index 索引处理插入元素 element boolean addAll(int index, Collection<? extends E> c) 在指定 index 索引处理插入集合元素 c
E remove(int index) 删除指定索引 index 处的元素

E set(int index, E element) 修改指定索引 index 处的元素为 element

E get(int index) + int size() for循环遍历集合中的每一个元素

ListIterator<E> listIterator() 通过列表迭代器遍历集合中的每一个元素 ListIterator<E> listIterator(int index) 通过列表迭代器从指定索引处开始正向或者逆向遍历集合中的元素

 

E get(int index) 获取指定索引处的元素
int indexOf(Object o) 从左往右查找,获取指定元素在集合中的索引,如果元素不存在返回 -1
int lastIndexOf(Object o) 从右往左查找,获取指定元素在集合中的索引,如果元素不存在返回 -1
List<E> subList(int fromIndex, int toIndex) 截取从 fromIndex 开始到 toIndex-1 处的元素
ArrayList

ArrayList 是一个数组队列,相当于 动态数组。与Java中的数组相比,它的容量能动态增长。它继承于AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable这些接口。ArrayList 继承了AbstractList,实现了List

它是一个数组队列,提供了相关的添加、删除、修改、遍历等功能。

ArrayList 实现了RandmoAccess接口,即提供了随机访问功能。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。在ArrayList中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问。

ArrayList 实现了Cloneable接口,即覆盖了函数clone(),能被克隆。

ArrayList 实现java.io.Serializable接口,这意味着ArrayList支持序列化,能通过序列化去传输。ArrayList的操作不是线程安全的。

扩容机制:当ArrayList不为空时,并且它的大小不超过10时,它的容量都是10.但当大小从10增加到11时,容量变成了15,扩大了1.5倍。
如果ArrayList的容量大于MAX_ARRAY_SIZE,来比较 minCapacity 和 MAX_ARRAY_SIZE,如果minCapacity大于最大容量,则新容量则为Integer.MAX_VALUE,否则,新容量大小则为 MAX_ARRAY_SIZE
即为 Integer.
MAX_VALUE - 8

Vector

Vector 类实现了一个动态数组。和 ArrayList 很相似,但是两者是不同的:

  • Vector 是同步访问的。
  • Vector 包含了许多传统的方法,这些方法不属于集合框架。

Vector 主要用在事先不知道数组的大小,或者只是需要一个可以改变大小的数组的情况。

第一种构造方法创建一个默认的向量,默认大小为 10;

Vector()

第二种构造方法创建指定大小的向量。
Vector(int size)
第三种构造方法创建指定大小的向量,并且增量用 incr 指定。增量表示向量每次增加的元素数目。
Vector(int size,int incr)
第四种构造方法创建一个包含集合 c 元素的向量:
Vector(Collection c)
Stack

栈是Vector的一个子类,它实现了一个标准的后进先出的栈。它也是线程安全的。

堆栈只定义了默认构造函数,用来创建一个空栈。 堆栈除了包括由Vector定义的所有方法,也定义了自己的一些方法。

Stack()除了由Vector定义的所有方法,自己也定义了一些方法:

 E push(E item)    把项压入堆栈顶部

E pop()    移除堆栈顶部的对象,并作为此函数的值返回该对象。 

E peek()    查看堆栈顶部的对象,但不从堆栈中移除它。 

boolean empty()    测试堆栈是否为空。

int search(Object o)    返回对象在堆栈中的位置,以 1 为基数。

Linkedlist
它继承了AbstractSequentialList 类,同时也实现了 Deque 接口

Linkedlist是线性数据结构,其中元素不存储在连续的位置,每个元素都是具有数据部分和地址部分的独立对象。元素使用指针和地址进行链接。每个元素被称为节点。由于插入和删除的动态性和易用性,它们优于阵列。

它也有一些缺点,比如节点不能直接访问,我们需要从头开始,然后通过链接到达我们希望访问的节点。 

为了将元素存储在链表中,我们使用一个双向链表,它提供了一个线性数据结构,并且还用于继承一个抽象类并实现list和deque接口。

以下情况使用 ArrayList :

  • 频繁访问列表中的某一个元素。
  • 只需要在列表末尾进行添加和删除元素操作。

以下情况使用 LinkedList :


  • 你需要通过循环迭代来访问列表中的某些元素。
  • 需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作。

Queue子接口

Queue接口与List、Set同一级别,都是继承了Collection接口。LinkedList实现了Queue接口。
队列的主要特点是在基本的集合方法之外,还提供特殊的插入、获取和检验操作。每个操作都提供两个方法,一种返回异常,一种返回null或者false.
队列一般满足先进先出规则(FIFO),除了优先队列(priority queue)和栈(stack),但是栈是FILO(先进后出规则),优先队列自己定义了排序规则。
队列不允许插入null元素,但是LinkedList可以

 java.ulil.concurrent包提供了阻塞队列的4个变种。默认情况下,LinkedBlockingQueue的容量是没有上限的,但是也可以选择指定其最大容量,它是基于链表的队列,此队列按 FIFO(先进先出)排序元素。

ArrayBlockingQueue在构造时需要指定容量, 并可以选择是否需要公平性,如果公平参数被设置true,等待时间最长的线程会优先得到处理(其实就是通过将ReentrantLock设置为true来 达到这种公平性的:即等待时间最长的线程会先操作)。通常,公平性会使你在性能上付出代价,只有在的确非常需要的时候再使用它。它是基于数组的阻塞循环队 列,此队列按 FIFO(先进先出)原则对元素进行排序。

PriorityBlockingQueue是一个带优先级的 队列,而不是先进先出队列。元素按优先级顺序被移除,该队列也没有上限(看了一下源码,PriorityBlockingQueue是对 PriorityQueue的再次包装,是基于堆数据结构的,而PriorityQueue是没有容量限制的,
与ArrayList一样,所以在优先阻塞 队列上put时是不会受阻的。虽然此队列逻辑上是无界的,但是由于资源被耗尽,所以试图执行添加操作可能会导致 OutOfMemoryError),但是如果队列为空,那么取元素的操作take就会阻塞,所以它的检索操作take是受阻的。
另外,往入该队列中的元 素要具有比较能力。
最后,DelayQueue(基于PriorityQueue来实现的)是一个存放Delayed 元素的无界阻塞队列,只有在延迟期满时才能从中提取元素。该队列的头部是延迟期满后保存时间最长的 Delayed 元素。
如果延迟都还没有期满,则队列没有头部,并且poll将返回null。当一个元素的 getDelay(TimeUnit.NANOSECONDS) 方法返回一个小于或等于零的值时,则出现期满,poll就以移除这个元素了。此队列不允许使用 null 元素。 下面是延迟接口:
- add(E e) 插入一个元素到队列中,失败时返回IllegalStateException (队列容量不够)
- element() 返回队列头部的元素
- offer(E e) 插入一个元素到队列中,失败时返回false
- peek() 返回队列头部的元素,队列为空时返回null
- poll() 返回并移除队列的头部元素,队列为空时返回null
- remove() 返回并移除队列的头部元素

Deque接口
双端队列是一种线性集合,可以从两端操作的队列。
  1. add(E e) 将新元素添加到队列的尾端(当不超过队列的容量时)
  2. addFirst(E e) 将新元素添加到队列的头部
  3. addLast(E e) 将新元素添加到队列的尾部
  4. contains(Object o) 双端队列是否含有对象o
  5. descendingIterator()倒叙返回队列的迭代器
  6. element() 返回队列的头部元素
  7. getFirst() 获取头部元素
  8. getLast() 获取尾部元素
  9. iterator() 迭代队列
  10. offer(E e) 将新元素插入到队列尾部
  11. offerFirst(E e) 将新元素添加到队列的头部
  12. offerLast(E e) 将新元素添加到队列的尾部
  13. peek() 返回队列的头部元素
  14. peekFirst() 获取头部元素
  15. peekLast() 获取尾部元素
  16. pool() 返回并移除队列的头部元素
  17. poolFirst() 获取并移除头部元素
  18. poolLast() 获取并移除尾部元素
  19. pop() 将一个元素出栈
  20. push(E e) 讲一个元素压入栈
  21. remove() 移除队列的头部元素
  22. remove(Object o) 移除队列中第一个o
  23. removeFirst() 移除队列的头部元素
  24. removeFirstOccurrence(Object o) 移除队列中第一个o
  25. removeLast() 移除队列的尾部元素
  26. removeLastOccurrence(Object o) 移除队列中最后一个o




posted @ 2021-01-10 12:34  codeZn  阅读(268)  评论(0)    收藏  举报