学习经验(四)

TreeSet、HashSet、LinkedHashSet的底层实现以及之间的区别;

HashSet和HashMap都是基于hash表(数组+链表)实现的,HashSet是基于HashMap实现
1、HashMap是key - value的存储方式;HashSet只存储元素对象

2、HashMap允许null值,key不重复,value可以重复;HashSet不允许重复,无序性

利用HashMap 的containsKey()方法,将对象元素作为key传入,然后就可以确保该元素在HashSet中的不重复性,另外根据add方法可以知道,HashSet在添加元素时,都是采用默认创建的PRESENT对象作为value填充到HashMap中的。因此可以实现利用HashMap来完成HashSet的操作。

小结:

1.对于HashSet中保存的对象,主要要正确重写equals方法和hashCode方法,以保证放入Set对象的唯一性
2.虽说是Set是对于重复的元素不放入,倒不如直接说是底层的Map直接把原值替代了(这个Set的put方法的返回值真有意思)
3.HashSet没有提供get()方法,愿意是同HashMap一样,Set内部是无序的,只能通过迭代的方式获得

LinkedHashSet(可以实现有序插入)
TreeMap默认按键的自然顺序升序进行排序
TreeSet特点与实现机制

TreeSet中存放的元素是有序的(不是插入时的顺序,是有按关键字大小排序的),且元素不能重复

而如何实现有序存储,就需要有一个比较器,其实说起来,TreeSet更受关注的是不重复且有序,这个有序就需要有一个compare的过程,因此会需要参数实现Comparable接口。

另外所有Set集合都不提供get方法,因为Set里面没有索引,若想遍历Set集合元素,有如下两种方式:

1、采用迭代器

2、增强for循环.

TreeMap底层实现数据结构是红黑树
PriorityQueue、LinkedBlockingQueue、ArrayBlockingQueue的实现以及区别;(太深)
HashMap的底层实现,扩容过程,达到阈值一定会扩容吗、put过程、树化过程,如何确定负载因子(有兴趣的可以看一下)、以及为什么线程不安全和1.8做了哪些优化;(太深)
HashMap与HashTable的区别(不知道都喜欢问这个,HashTable已经弃用了),如何获得一个线程安全的Map;
ConcurrentHashMap为什么是线程安全的,以及1.8做了哪些优化;
ConcurrentHashMap原理分析(锁分离技术)
1 、结构

由hash表、segment(桶)、hashEntry(节点)组成
注:每个segment都继承了ReentrantLock

2、hash过程

步骤一:第一次hash,h1=hash1(key);
步骤二:第二次hash找出segment的位置,h2=hash2(h1高几位)
步骤三:第三次hash找出hashEntry的位置,h3=hash3(h2)

  • 插入时从hashEntry链表的头插入,删除时会拷贝一份新的数据链,删除线程和遍历线程不会相互影响
3、concurrentLevel:并发级别,决定segment的个数,最大为1<<16

换句话说,segment的个数代表了并发量

JDK1.8之后的改进:

链表改成了红黑树,当链表中的结点达到一个阀值TREEIFY_THRESHOLD时,会将链表转换为红黑树,查询效率提从原来的O(n),提高为O(logn)

将每个segment的分段锁ReentrantLock改为CAS+Synchronized

问题汇:
  • HashMap的get和put的工作原理?

1、数组+链表的结构

2、get(key)时,会用key做一次hash运算得到hashcode,根据hashcode找到数组的位置,然后查看对应数组下是否有链表,有则遍历看链表中的结点Node是否有key相等的结点,如果有则返回此结点的value,无则继续

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值