java之集合概述

整体类图

image

Java集合是java提供的工具包,包含了常用的数据结构:集合、链表、队列、栈、数组、映射等。Java集合工具包位置是java.util.*
Java集合主要可以划分为4个部分:List列表、Set集合、Map映射、工具类(Iterator迭代器、Enumeration枚举类、Arrays和Collections)。

接口

上图中看到 主要的接口类为:Collection 和 Map。

继承Collection的接口主要有三大类:List、Set、Queue;实现Collection接口的AbstractCollection

继承Map接口的主要有:SortedMap ,实现Map的有AbstractMap 以及HashTable

list

List是一个有序的队列,每一个元素都有它的索引。第一个元素的索引值是0。List的实现类有LinkedList, ArrayList, Vector, Stack。

  • LinkedList:底层数据结构为双向链接队列,可以被当作栈、队列或双端队列来使用。非线程安全
  • ArrayList:基于动态数组的数据结构。因此对于随机访问get和set,ArrayList要优于LinkedList,因为LinkedList要移动指针;理论上当要在ArrayList非尾部index处插入数据,index之后的所有元素,会被移动会导致插入效率变低。非线程安全
  • Vector :基于动态数组的数据结构。是线程安全的(相对线程安全)。主要用在事先不知道数组的大小,或者只是需要一个可以改变大小的数组的情况。默认数组大小为 10,如果未指定扩容大小,扩容时按现在数据大小的两倍扩容。
  • stack :是Vector的一个子类,它实现了一个标准的后进先出的栈。

set

Set是一个不允许有重复元素的集合。 Set的实现类有HastSet和TreeSet。HashSet依赖于HashMap,它实际上是通过HashMap实现的;TreeSet依赖于TreeMap,它实际上是通过TreeMap实现的。

  • HastSet:通过HashMap实现。 HashSet 中的所有元素都是保存在 HashMap 的 key 中,value 则是使用的 PRESENT 对象,该对象为 static final Object。默认的初始容量为16,负载因子为0.75.
  • TreeSet:是基于 TreeMap 实现的,TreeMap是一个有序的二叉树,那么同理TreeSet同样也是一个有序的,它的作用是提供有序的 Set 集合。

HashMap

基于哈希表的 Map 接口的实现,以 key-value 的形式存在。初始化时,最为重要的两个参数为:初始容量和负载因子

  • 初始容量:表示哈希表中桶的数量,初始容量是创建哈希表时的容量

  • 加载因子:是哈希表在其容量自动增加之前可以达到多满的一种尺度,它衡量的是一个散列表的空间的使用程度,负载因子越大表示散列表的装填程度越高,反之愈小。对于使用链表法的散列表来说,查找一个元素的平均时间是O(1+a),因此如果负载因子越大,对空间的利用更充分,然而后果是查找效率的降低;如果负载因子太小,那么散列表的数据将过于稀疏,对空间造成严重浪费。系统默认负载因子为 0.75,一般情况下我们是无需修改的。

  • Put过程:首先判断 key 是否为 null,若为 null,则直接调用 putForNullKey 方法。若不为空则先计算 key 的 hash 值,然后根据 hash 值搜索在 table 数组中的索引位置,如果 table 数组在该位置处有元素,则通过比较是否存在相同的 key,若存在则覆盖原来 key 的 value,否则将该元素保存在链头(最先保存的元素放在链尾)。若 table 在该处没有元素,则直接保存。

  • Get过程:若为null,直接取第一个;若不为空则先计算 key 的 hash 值,然后根据 hash 值搜索在 table 数组中的索引位置。然后返回该 key 对应的 value 即可。

  • HashMap 的底层数组长度总是 2 的 n 次方,在构造函数中存在:capacity <<= 1;这样做总是能够保证 HashMap 的底层数组长度为 2 的 n 次方。当 length 为 2 的 n 次方时,h&(length – 1) 就相当于对 length 取模,而且速度比直接取模快得多,这是 HashMap 在速度上的一个优化。

TreeMap

TreeMap 实现是红黑树算法的实现。红黑树是一颗自平衡的排序二叉树,即根节点大于左子树小于右子树。所以TreeMap是有序的Map结构

WeakHashMap

WeakHashMap的存储结构等与HashMap的结构几乎一样,不同指出是其引用是弱引用。所谓弱引用是指,java垃圾回收器,在检查到该引用是弱引用的时候,不管内存是否够用都会对此引用进行垃圾回收。

HashTable

实现Map接口,继承了Dictionary。HashTable采用”拉链法”实现哈希表,它定义了几个重要的参数:table、count、threshold、loadFactor、modCount。

table:为一个Entry[]数组类型,Entry代表了“拉链”的节点,每一个Entry代表了一个键值对,哈希表的”key-value键值对”都是存储在Entry数组中的。

count:HashTable的大小,注意这个大小并不是HashTable的容器大小,而是他所包含Entry键值对的数量。

threshold:Hashtable的阈值,用于判断是否需要调整Hashtable的容量。threshold的值=”容量*加载因子”。

loadFactor:加载因子。

modCount:用来实现“fail-fast”机制的(也就是快速失败)。所谓快速失败就是在并发集合中,其进行迭代操作时,若有其他线程对其进行结构性的修改,这时迭代器会立马感知到,并且立即抛出ConcurrentModificationException异常,而不是等到迭代完成之后才告诉你(你已经出错了)。

HashTable与HashMap的区别

第一: 我们从他们的定义就可以看出他们的不同,HashTable基于Dictionary类,而HashMap是基于AbstractMap。Dictionary是什么?它是任何可将键映射到相应值的类的抽象父类,而AbstractMap是基于Map接口的骨干实现,它以最大限度地减少实现此接口所需的工作。
第二: HashMap可以允许存在一个为null的key和任意个为null的value,但是HashTable中的key和value都不允许为null。
第三: Hashtable的方法是同步的,而HashMap的方法不是。

猜你喜欢

转载自www.cnblogs.com/lotorless/p/10285436.html