首页 > 编程语言 > 详细

关于java容器的问题

时间:2020-09-27 21:38:49      阅读:34      评论:0      收藏:0      [点我收藏+]

1.HashMap 和 Hashtable 有什么区别?

HashMap和HashTable区别主要有以下几点:
1.线程的安全性。HashTable的大部分方法都使用了Synchronize同步锁,使得HashTable在多线程环境下变得安全,而HashMap则不是。
2.效率。HashTable因为加了同步锁导致效率变低。
3.存值。HashMap可以存储k-v,null-null,k-null,null-k(只能有一个k值为null),而HashTable只能存储k-v。
4.扩容方式。HashMap初始容量为16,扩容方式为2n,HashTable初始容量为11,扩容方式为2n+1。

2.ArrayList 和 LinkedList 的区别是什么?

ArrayList 和 LinkedList 的区别主要有以下几点:
1.底层数据结构不同。ArrayList底层为动态数组,LinkedList底层为双向链表。
2.针对场景不同。ArrayList适用于查询多,增删少的场景,LinkedList相反。

3.Iterator 怎么使用?有什么特点?

Collection下的子类都实现了这个iterator()方法,可以用对象直接调用。
它的特点主要有两个,1.使用Iterator遍历集合时,不允许对集合进行修改,否则抛出异常;2.使用Iterator 遍历集合时,可以用remove方法移除元素。

4.Iterator 和 ListIterator 有什么区别?

主要有以下几点:
1.ListIterator继承了Iterator 接口,额外添加了一些方法,比如添加一个元素,替换一个元素,获取前面或后面元素的索引。
2.Iterator 可以遍历List和Set两种集合,ListIterator 只能遍历List。
3.Iterator 只能单向遍历,ListIterator 可以双向遍历。

5.说一下 HashMap 的实现原理?

HashMap底层的数据结构是数组和链表/红黑树,其中每个元素都是链表,通过.put()和.get()进行存取值,
首先,当把key值传入时,会进行.hashcode()计算出key的哈希值,根据哈希值计算出对应的数组下标,然后将元素放入,这时会出现两种情况,第一种是数组的该位置没有存值,这时直接插入即可,第二种是出现哈希冲突,该位置有值,这时就要将传入的key和该位置的key值进行equals比较,比较的结果若相同,则将传入的value存入覆盖掉原先的值,比较的结果若不相同,则在该位置的链表上插入,1.7进行头插,1.8尾插;1.7会在插入前判断扩容,1.8会在插入后进行判断扩容;1.8会在链表大于8时将链表转化为红黑树。
用.get()取值时,先将传入的key计算哈希值,计算出对应的数组下标得到该key在数组中的位置,然后equals比较两key值是否相等,相等取出该value,不相等则取链表上后续元素的key进行比较,直到相等返回,或者没有相等的返回null。

6.你知道 hash 的实现吗?为什么要这样实现?

7.说说你对红黑树的见解?

8.HashMap 的 table 的容量如何确定?loadFactor 是什么?该容量如何变化?这种变化会带来什么问题?

1.table的容量由capacity参数确定,默认的初始容量是16,最大值为1<<30。
2.loadFactor代表负载因子,主要用于确定map扩容的阈值,比如,默认的初始容量为16,扩容阈值为12,当hashMap的实际存储元素数量size达到12时,进行扩容。
3.容量变化的方式为扩大为原来的两倍。
4.容量的变化会带来性能的影响,当性能要求比较高时,这种性能损失比较致命。

9.拉链法导致的链表过深问题为什么不用二叉查找树代替,而选择红黑树?为什么不一直使用红黑树?

因为二叉树可能会出现特殊的情况,即二叉树形成线性结构,和链表结构一样,所以不能用二叉树。不能一直使用红黑树是因为引入红黑树是为了提高查找效率,当链表的长度大于8时,红黑树在自平衡时的性能消耗小于遍历链表的消耗,小于8时红黑树自平衡的消耗要大于遍历链表的消耗。

10.数组扩容的过程?

在扩容时,会先新建一个新容量为原来容量两倍的数组,并重新计算旧数组节点的存储位置,节点在新数组中的位置只有两种,原下标或者原下标+旧数组大小。

11.jdk8中对HashMap做了哪些改变?

1.数据结构变了。1.7中数据结构为数组+链表,1.8为数组+链表+红黑树,当链表长度大于8时,会将链表转化为红黑树,小于6时,将红黑树转化成链表。
2.链表的插入方式变了。1.7中的插入方式为头插法,1.8为尾插法。
3.Entry被Node替代。

12.怎么确保一个集合不能被修改?

使用Collections的unmodifiableCollection方法将集合变为不可修改的。

13.Java 中的另一个线程安全的与 HashMap 极其类似的类是什么?同样是线程安全,它与 HashTable 在线程同步上有什么不同?(HashMap & ConcurrentHashMap 的区别?)

java.util.concurrent并发包下的ConcurrentHashMap。同样的线程安全,ConcurrentHashMap1.7使用的是分段锁,1.8使用的是CAS(无锁算法)+ synchronized,HashTable使用的是Synchronized同步锁,前者将Map中的某个Segment(1.7)或者Node(1.8)锁住,后者将整个map锁住,效率上存在明显的差距。

14.针对 ConcurrentHashMap 锁机制具体分析(JDK 1.7 VS JDK 1.8)?

  1. 1.7中使用的是分段锁,Segment 继承 ReentrantLock(重入锁) 用来充当锁的角色,每个 Segment 对象守护每个散列映射表的若干个桶,每个桶即为数组的一个元素,这个元素为链表,包含多个HashEntry(键值对),每次锁的时候是锁住某segment对象,即锁住了数组上若干个元素,颗粒度是Segment。
  2. 1.8中使用的CAS + Synchronized锁,取消了segment,上锁时锁住的是某个数组的元素,即链表中的首个Node,颗粒度是Node。

15.ConcurrentHashMap 在 JDK 1.8 中,为什么要使用内置锁 synchronized 来代替重入锁 ReentrantLock?

1.粒度降低了;
2.JVM 开发团队没有放弃 synchronized,而且基于 JVM 的 synchronized 优化空间更大,更加自然。
3.在大量的数据操作下,对于 JVM 的内存压力,基于 API 的 ReentrantLock 会开销更多的内存。

16.ConcurrentHashMap 的并发度是什么?

程序运行时能够同时更新 ConccurentHashMap 且不产生锁竞争的最大线程数。默认为 16,且可以在构造函数中设置。当用户设置并发度时,ConcurrentHashMap 会使用大于等于该值的最小2幂指数作为实际并发度(假如用户设置并发度为17,实际并发度则为32)。

17.HashMap 容量为什么总是为 2 的次幂?

18.hashMap有用到了泊松分布和二项分布吗,有的话在哪里用到的?

关于java容器的问题

原文:https://www.cnblogs.com/thePeaceOftheLord/p/13741245.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!