六、java集合

1、java集合的常规比较(安全性已经知道)
(1)HashMap:初始容量16、扩容两倍、extends AbstractMap implements Map
长度是2的幂次方能让HashMap存取高效,尽量较少碰撞,也就是要尽量把数据分配均匀。hash%length==hash&(length-1)采用二进制位操作&,相对于%能够提高运算效率,这就解释了HashMap的长度为什么是2的幂次方。
(2)HashSet:初始容量16、扩容两倍、
(3)Hashtable:初始容量11、扩容2倍+1、extends Dictionary implements Map
初始容量为11的原因是除(近似)质数求余的分散效果好,创建时如果给定了容量初始值,那么Hashtable会直接使用你给定的大小
(3)ArrayList:jdk1.8之前,初始容量10、扩容1.5倍+1,JDK1.8以后是0,然后首次增加到10,以后每次增加到1.5倍,底层是Arrays的数组拷贝来实现的。
(4)StringBuffer、初始容量16、扩容2倍+2或者是count+str.length()
(5)Vector扩容两倍

2、JDK1.8中ConcurrentHashMap中的CAS和synchronized在哪使用的
CAS:在判断数组中当前位置为null的时候,使用CAS来把这个新的Node写入数组中对应的位置
synchronized:当数组中的指定位置不为空时,通过加锁来添加这个节点进入数组(链表<8)或者是红黑树(链表>=8)

3、Arrays.asList方法后的List可以扩容吗?
Arrays.asList使用的是final数组,并且不支持add方法,不支持扩容。

4、HashMap中hash函数做了哪些改动?(1.7->1.8
让hashCode取值出的高位也参与运算,进一步降低hash碰撞的概率,使得数据分布更平均,我们把这样的操作称为扰动,在JDK1.8中的hash()函数如下:
(key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
// 与自己右移16位进行异或运算(高低位异或)
这比在JDK1.7中,更为简洁,相比在1.7中的4次位运算,5次异或运算(9次扰动),在1.8中,只进行了1次位运算和1次异或运算(2次扰动)
注:回答Hashmap的时候,先从结构->put->扩容

5、Comparable和Comparator的区别?
Comparable是排序接口,若一个类实现了Comparable接口,就意味着“该类支持排序”。而Comparator是比较器,我们若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序。若类实现了Comparable接口,则针对该类的集合可以直接调用Collections.sort(和Arrays.sort)进行自动排序。
Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。
两种方法各有优劣:
用Comparable简单,只要实现Comparable接口的对象直接就成为一个可以比较的对象,但是需要修改源代码。
用Comparator的好处是不需要修改源代码,而是另外实现一个比较器,当某个自定义的对象需要作比较的时候,把比较器和对象一起传递过去就可以比大小了,并且在Comparator里面用户可以自己实现复杂的可以通用的逻辑,使其可以匹配一些比较简单的对象,那样就可以节省很多重复劳动了。

6、lambda表达式中使用外部变量,为什么要final?
(1)外部变量定义在栈中,当Lambda表达式被执行的时候,变量可能已经被释放掉了。
(2)在JDK8之后,匿名内部类引用外部变量时虽然不用显式的用final修饰,但是这个外部变量必须和final一样,不能被修改,
(3)解决方案:可以通过定义一个相同类型的变量b,然后将该外部变量赋值给b,匿名内部类引用b就行了,然后就可以继续修改外部变量。

10、Enumeration和Iterator接口的区别?
(1)Enumeration的速度是Iterator的两倍,也使用更少的内存。Enumeration是非常基础的。
(2)但是,与Enumeration相比,Iterator更加安全,因为当一个集合正在
被遍历的时候,它会阻止其它线程去修改集合

11、为何Iterator接口没有具体的实现?
Iterator接口定义了遍历集合的方法,但它的实现则是集合实现类的责任。每个能够返回用
于遍历的Iterator的集合类都有它自己的Iterator实现内部类。
这就允许集合类去选择迭代器是fail-fast还是fail-safe的。比如,ArrayList迭代器是fail-fast的,而CopyOnWriteArrayList迭代器是fail-safe的。

12、HashMap在并发环境下会出现什么样的问题(环的问题)?
(1)Hashmap的Resize包含扩容和ReHash两个步骤,ReHash在并发的情况下可能会形成链表环。
(2)Hashmap在并发情况下还会造成size不准确(因为在判断是否需要扩容之前会做size++,其实这个时候size实际可能只是增加了1,现在确增加了2)

13、为什么 Collection 不从 Cloneable 和 Serializable 接口继承
Collection是一个接口。而克隆和序列化只对于具体的类有意义,你不能说去把一个接口,抽象类克隆,序列化甚至反序列化。

14、可以在 hashcode() 中使用随机数字吗?
不行,因为对象的 hashcode 值必须是相同的。

15、HashsSet为什么无序,为什么不重复?
1、HashSet集合操作,是将数据值存入至HashMap的key中;
2、hsahmap在保存数据时,顺序是通过计算key的hash值和当前数组长度的 & 运算,计算保存数据的下标位置。所以说set是无序的。
3、由于每次保存数据,存入的是一个共同的值:
private static final Object PRESENT = new Object();
当存在key的hash与数组大小 & 计算到的值存在数组中时,则会进行新的值的覆盖,所以说set是不重复的。

16、ConcurrentHashMap的size()方法是如何计算的?
JDK1.7 和 JDK1.8 对 size 的计算是不一样的。1.7 中是先不加锁计算三次,如果三次结果不一样在加锁。
JDK1.8 size 是通过对baseCount和counterCell 进行 CAS 计算,最终通过 baseCount 和 遍历 CounterCell 数组得出 size。

18、Collections中shuffle()是如何实现的?
RandomAccess实例的时候直接执行了for循环,在这个for循环中调用了swap方法:swap方法中接收的参数j是一个随机数,将这个随机数j作为索引位置

20、HashMap经过迭代器取出来的数据顺序和放入顺序一致么?
不一致,数组+链表,数组的位置不确定

21、HashMap的扩容的时间复杂度,如何优化?
JDK1.7:
第一:rehash重新分配数组,因此rehash之后的元素是不固定的
第二:由于在1.7中使用的是头插法,并发场景可能会造成环的现象;
JDK1.8
第一:元素的位置要么是在原位置,要么是在原位置再移动2次幂的位置。因为扩容是2倍,相当于右移了一位,通过hash & (length - 1) :判断元素的位置在哪?如果是0的话索引没变,是1的话索引变成“原索引+oldCap”
第二:采用尾插法不会造成环的现象

22、往set里面put一个学生对象,然后将这个学生对象的学号改了,再put进去,可以放进set么?
答:不可以放入,因为修改学号并不会修改这个学生对象的hashcode,set不能存放相同(使用equals判断成立)的元素,修改hashcode的生成方法即可放入

23、hashmap set方法时间复杂度
不管插入还是查找,由key获取hash值然后定位到桶的时间复杂度都是O(1),那么真正决定时间复杂度的实际上是桶里面链表/红黑树的情况
如果桶里面没有元素,那么直接将元素插入/或者直接返回未查找到,时间复杂度就是O(1),如果里面有元素,那么就沿着链表进行遍历,时间复杂度就是O(n),链表越短时间复杂度越低,如果是红黑树的话那就是O(logn)
所以平均复杂度很难说,只能说在最优的情况下是O(1)

24、hashMap如何计算hash的
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
1、计算出key值的hashcode;
2、h = key.hashCode()) ^ (h >>> 16)可以理解为hashcode高16位右移,作为低16位,与hashcode进行异或^运算,;
使用异或运算可以使得hash值更加均匀减少冲突

25、为什么 1.8 不使用 分段锁了
(1)分段锁的锁粒度太大
(2)1.8使用了cas,底层是基于unsafe的,unsafe是直接操作操作体系指针的,效率高、

25、当链表元素个数大于8的时候,就会转换为红黑树;当红黑树元素个数小于6的时候,就会转换回链表。
链表转换为红黑树的最终目的,是为了解决在map中元素过多,hash冲突较大,而导致的读写效率降低的问题。到8的是因为时间复杂度

26、ArrayList中删除值为指定的数,能够直接 remove吗?会有什么问题
如果直接remove,比如remove了位置为0的元素,则后面的元素会前移,之前的index为1的 index就变成了0,所以会有问题

27、HashMap与HashTable的区别
(1)继承关系不同
ashMap Map
Cloneable
Serializable AbstractMap
HashTable Dictionary
(2)安全性不同
(3)迭代器不同
HashMap Iterator fail-fast
HashTable Enumerator 非fail-fast
(4)新增元素是否为空的要求不同

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值