Java面试题-集合与数组

1. 集合架构:

  • Collection:子接口有ListSet
	List:实现类有ArrayList、LinkedList、Vector;存取有序,可存储重复元素;支持通过下标访问;
		Vector:底层采用数组实现;方法基本被synchronized修饰,线程安全;
		ArrayList:底层采用数组实现,随机访问效率高;因数组存储需要连续的内存,增删时需要移动其他元素的索引,而且扩容时需要拷贝元素,
		所以增删效率低;尾部增删时效率高;线程不安全;
		LinkedList:底层采用双向链表实现,增删时只需要修改头、尾结点的指向,增删效率比ArrayList高;无法通过数组下标随机访问
		(get()方法每次都会遍历),需要遍历,所以查找效率比ArrayList低;线程不安全;
	Set:实现类有HashSet、LinkedHashSet、TreeSet;存取无序,可去重;只能通过遍历访问;
		HashSet:底层采用`HashMap`实现;存储的对象需要重写HashCode()和equals()方法;只有HashCode()返回值相同且equals()返回true才会存储;
		LinkedHashSet:继承了HashSet,同时保证了存取有序;
		TreeSet:底层采用TreeMap实现,可对存储对象进行排序;存储对象需要实现Comparable接口并重写comPareTo(),comPareTo()返回0不存、
		返回正数怎么存怎么取、返回负数倒序存储;
Map:实现类有HashMap、TreeMap、HashTable;存储key-value类型;不能存储重复元素
	HashTable:方法被synchronized修饰,线程安全;不能存储null键和null值;
	HashMap:线程不安全,能存储null键和null值;
	LinkedHashMap:继承了HashMap,同时保证了存取有序;
	TreeMap:底层是二叉树算法;

2. HashMap存取过程:

  • jdk1.8之前HashMap底层采用数组+链表的结构,HashMap调用put(key,value)存储对象时,会先调用hash()计算存储位置:用key的hashCode与hashCode右移16位进行异或运算((h = key.hashCode()) ^ (h >>> 16))得到数组下标,然后将Entry对象存储在对应位置的链表上,jdk1.7采用头插法,效率高;
    为什么进行异或运算(为什么不用求余运算)
    (h = key.hashCode()) ^ (h >>> 16)高位不变,后16位高低混合,采用异或操作能更好的保留各部分的特征;重新计算出的hash值会参与数组下标的计算((n - 1) & hash),n为数组大小,为2的次幂,如果数组大小太小,高位全是0,会损失高位特征,计算出来的两个哈希值很接近,容易导致哈希碰撞。
    哈希碰撞:不同对象计算出来的hashcode值可能相同,put()发生碰撞后,Entry对象会存储在链表上;
    为什么数组大小是2的次幂
    ((n - 1) & hash)计算数组下标,2n-1能保证二进制有更多的1,在&运算避免损失更多特征,让结果分布的更加均匀,避免哈希碰撞。因为数组大小为2的次幂,而数组扩容为原来的两倍,也是2的次幂,这样按位与操作的值的变化就是二进制高位+1,比如16扩容到32,二进制变化就是从0000 1111(即15)到0001 1111(即31),那么这种变化就会使得需要扩容的元素的哈希值重新按位与操作之后所得的下标值要么不变,要么+16,能使得原本在同一个链表上的元素均匀(相隔扩容后的容量的一半)分布到新的哈希表中;
    数组扩容:HashMap数组默认大小为16,加载因子为0.75,扩容大小为2倍;当数组存储了12个元素时会进行扩容,新数组大小为32;
    当用get(key)获取时,会调用hash()计算key的值找到数组位置,因为链表中存储的是键值对,再调用key.equals()找到值对象;

  • jdk1.8HashMap底层采用数组+链表+红黑树的结构,当链表的长度大于8时转为红黑树,当红黑树长度小于6时转为链表

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值