Java回顾

1.集合框架

目前常用的集合框架有List、Set、Map。其中List、Set接口继承于Collection接口。

List:有序、可重复。(队列)

ArrayList:通过数组保存数据。初始大小为10,每次扩容由为当前容量的一半,若一次添加的元素较多,扩容一次后的容量仍然不足以满足需求,则根据当前ArrayList中含有的数据个数+需要添加的元素的个数之和为ArrayList集合新的大小。

Vector:通过数组保存数据。矢量队列,JDK1.0版本添加的类。队列结构,初始默认大小为10,每次扩容,若容量增加系数>0,则新的容量=当前容量+容量增加系数,否则容量增加一倍。Vector所有方法都用synchronized关键字进行修饰,Vector结构具有数据同步。

LinkedList:双向链表。可被当作堆栈、队列(实现List)、双端队列(实现Deque )、能进行序列化传输(实现Serializable接口)。Entry是双向链表节点所对应的数据结构,它包括的属性有:当前节点所包含的值上一个节点下一个节点。LinkedList实现java.io.Serializable。当写入到输出流时,先写入“容量”,再依次写入“每一个节点保护的值”;当读出输入流时,先读取“容量”,再依次读取“每一个元素”。可以作为FIFO(先进先出)的队列,也可作为LIFO(后进先出)的栈

Stack:栈,先进后出(FILO, First In Last Out),初始大小为10,java工具包中的Stack是继承于Vector(矢量队列)的,由于Vector是通过数组实现的,这就意味着,Stack也是通过数组实现的而非链表。当然,我们也可以将LinkedList当作栈来使用!

Set:无序、不可重复。

AbstractSet 是一个抽象类,它继承于AbstractCollection,AbstractCollection实现了Set中的绝大部分函数,为Set的实现类提供了便利。
HashSet继承于AbstractSet,并且实现了Set接口,依赖于HashMap,它实际上是通过HashMap实现的。HashSet中的元素是无序的,允许使用null元素,非同步。HashSet中含有一个"HashMap类型的成员变量"map,HashSet的操作函数,实际上都是通过map实现的,默认HashSet的长度和HashMap的长度相同,因为在创建HashSet时实际上是创建的HashMap而HashMap的默认长度为16,每次当HashSet中存储的数据个数达到阀值时就会进行扩容,每次扩容与HashMap的扩容方式相同,增加两倍。


TreeSet依赖于TreeMap,它实际上是通过TreeMap实现的。TreeSet中含有一个"NavigableMap类型的成员变量"m,而m实际上是"TreeMap的实例",TreeSet中的元素是有序的,非线程安全,。

TreeSet 继承于AbstractSet,所以它是一个Set集合,具有Set的属性和方法。
TreeSet 实现了NavigableSet接口,意味着它支持一系列的导航方法。比如查找与指定目标最匹配项。
TreeSet 实现了Cloneable接口,意味着它能被克隆。
TreeSet 实现了java.io.Serializable接口,意味着它支持序列化。

TreeSet中的元素支持2种排序方式:自然排序 或者 根据创建TreeSet 时提供的 Comparator 进行排序。这取决于使用的构造方法。当我们构造TreeSet时;若使用不带参数的构造函数,则TreeSet的使用自然比较器;若用户需要使用自定义的比较器,则需要使用带比较器的参数。

TreeSet实现java.io.Serializable的方式。当写入到输出流时,依次写入“比较器、容量、全部元素”;当读出输入流时,再依次读取。

 

Map:映射接口存储内容:键值对(Key—Value)

AbstractMap:抽象类,继承于Map,实现Map中大部分API。其他Map实现类可以通过继承AbstractMap来减少重复代码。

SortedMap:接口,继承Map。实现该接口的类存储内容是排序的键值对,排序方法通过比较器实现(Comparator)

NavigableMap:接口,继承SortedMap。相比于SortedMap,NavigableMap有一系列导航方法。eg:获取大于/等于某对象的键值对、获取小于/等于某对象的键值对等等。

 

TreeMap:实现类。,红黑树实现,继承AbstractMap,实现NavigableMap、Cloneable、java.io.Serializable接口;特点:存储有序键值对,能被克隆、能被序列化,非同步的。

TreeMap的本质是R-B Tree(红黑树),它包含几个重要的成员变量: root, size, comparator。
  root 是红黑数的根节点。它是Entry类型,Entry是红黑数的节点,它包含了红黑数的6个基本组成成分:key(键)、value(值)、left(左孩子)、right(右孩子)、parent(父节点)、color(颜色)。Entry节点根据key进行排序,Entry节点包含的内容为value。
  红黑数排序时,根据Entry中的key进行排序;Entry中的key比较大小是根据比较器comparator来进行判断的。
  size是红黑数中节点的个数。

HashMap:实现类。继承AbstractMap,实现了Map、Cloneable、java.io.Serializable接口,没有实现NavigableMap;特点:散列表,键值对,不保证次序,不同步,Key-Value都可为null(且放在table[0]的位置),默认初始大小16(必须是2的幂,最大2的30次幂),每次到达阀值HashMap的容量扩增2倍,直至满足需求,默认加载因子0.75。

HashMap 的实例有两个参数影响其性能:“初始容量” 和 “加载因子”。容量 是哈希表中桶的数量,初始容量 只是哈希表在创建时的容量。加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash 操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数。
通常,默认加载因子是 0.75, 这是在时间和空间成本上寻求一种折衷。加载因子过高虽然减少了空间开销,但同时也增加了查询成本(在大多数 HashMap 类的操作中,包括 get 和 put 操作,都反映了这一点)。在设置初始容量时应该考虑到映射中所需的条目数及其加载因子,以便最大限度地减少 rehash 操作次数。如果初始容量大于最大条目数除以加载因子,则不会发生 rehash 操作。

        HashMap继承于AbstractMap类,实现了Map接口。Map是"key-value键值对"接口,AbstractMap实现了"键值对"的通用函数接口。
       HashMap是通过"拉链法"(解决哈希冲突)实现的哈希表。它包括几个重要的成员变量:table, size, threshold, loadFactor, modCount。
  table是一个Entry[]数组类型,而Entry实际上就是一个单向链表。哈希表的"key-value键值对"都是存储在Entry数组中的。
  size是HashMap的大小,它是HashMap保存的键值对的数量。
  threshold是HashMap的阈值,用于判断是否需要调整HashMap的容量。threshold的值="容量*加载因子",当HashMap中存储数据的数量达到threshold时,就需要将HashMap的容量加倍。
  loadFactor就是加载因子。
  modCount是用来实现fail-fast机制的。

 

HashTable:实现类。继承Dictionary(键值对接口),实现了Map、Cloneable、java.io.Serializable接口。特点:散列表结构,键值对,不保证次序,线程安全,key-Value不能为null,默认大小为11,每次扩增将长度变为原来的2倍+1。

1.Hashtable继承于Dictionary类,实现了Map接口。Map是"key-value键值对"接口,Dictionary是声明了操作"键值对"函数接口的抽象类。

2.Hashtable是通过"拉链法"实现的哈希表。它包括几个重要的成员变量:table, count, threshold, loadFactor, modCount。
  table是一个Entry[]数组类型,而Entry实际上就是一个单向链表。哈希表的"key-value键值对"都是存储在Entry数组中的。
  count是Hashtable的大小,它是Hashtable保存的键值对的数量。
  threshold是Hashtable的阈值,用于判断是否需要调整Hashtable的容量。threshold的值="容量*加载因子"。
  loadFactor就是加载因子。
  modCount是用来实现fail-fast机制的

WeakHashMap:实现类。继承AbstractMap。特点:键值对(键和值都可以是null),不保证次序,弱键。结构:散列表。初始大小:默认大小16,最大容量2的30次方,默认加载因子为0.75,每次扩充的容量为当前容量*2,若当前结构保存的键值对的数量达到了预设的阀值,则对结构进行扩容处理。阀值=容量*加载因子。

在 WeakHashMap 中,当某个键不再正常使用时,会被从WeakHashMap中被自动移除。更精确地说,对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的丢弃,这就使该键成为可终止的,被终止,然后被回收。某个键被终止时,它对应的键值对也就从映射中有效地移除了。
    这个“弱键”的原理呢?大致上就是,通过WeakReference和ReferenceQueue实现的。 WeakHashMap的key是“弱键”,即是WeakReference类型的;ReferenceQueue是一个队列,它会保存被GC回收的“弱键”。实现步骤是:
    (01) 新建WeakHashMap,将“键值对”添加到WeakHashMap中。
           实际上,WeakHashMap是通过数组table保存Entry(键值对);每一个Entry实际上是一个单向链表,即Entry是键值对链表。
   (02) 当某“弱键”不再被其它对象引用,并被GC回收时。在GC回收该“弱键”时,这个“弱键”也同时会被添加到ReferenceQueue(queue)队列中。
   (03) 当下一次我们需要操作WeakHashMap时,会先同步table和queue。table中保存了全部的键值对,而queue中保存被GC回收的键值对;同步它们,就是删除table中被GC回收的键值对

HashMap与WeakHashMap都是不同步的。可以使用 Collections.synchronizedMap 方法来构造同步的 WeakHashMap。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值