2/7牛客网阿里面试——主要HashMap

1.Object中的方法:
1.protected native Object clone() throws CloneNotSupportedException
克隆方法
——用于对象拷贝,所以你所创建的类必须要继承Cloneable接口否则报错。
class Person implements Cloneable{
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();//无论深浅拷贝都需要的一句话!代表调用object的clone方法
}
}
在这里插入图片描述
上边是引用的复制,Person p=newPerson(23,“zhang”),Person p1=p
这不叫拷贝。

在这里插入图片描述
注:
0.clone方法最终返回Object对象
1.浅克隆是克隆对象所有变量都含有与原来相同的值,而所有的对其他对象的引用仍然指向原来的对象
2.深克隆就是把克隆的对象引用对象全都克隆一遍。
3.实现深度克隆的方式,必须重写clone()方法,Student0 s2 = (Student0) s1.clone();这种强转实现重写
4.所以浅克隆就有个问题,一旦一个指向的修改了值,对于另外一个的值也会改了,因为引用的相同啊。
5.java创建新对象,有两种方式new和clone
6.new创建对象时,首先查看new操作符后面的类型,知道了对象类型,才知道分配多大的内存空间。分配内存之后,再调用构造器函数,填充对象的个域,然后将他的引用(地址)发布到外部,通过引用操作对象。clone也一样。
2.public final native Class<?> getClass(); 获得运行时的类型,。这个方法可以引出有关反射,类加载机制
3.public native int hashCode(); 这里会引出hashmap实现原理
4.public boolean equals(Object obj) 这里会引出hashmap实现原理
注:
1.equals方法与==是等价的,比较的都是引用地址(指向谁),但是我们大部分开发中都重写equals,比较属性值是否相等。
2.equals()相等,hashCode就一定要相等,而hashCode相等,却不要求equals相等
3. 为什么需要hashCode?通过hashCode可以很快的查到小内存块。通过hashCode比较比equal方法快,当get时先比较hashCode,如果hashCode不同,直接返回false。
5.public String toString()
6.public final native void notify(); 这里会引出线程通信
7.public final native void notifyAll()
8.public final native void wait(long timeout) throws InterruptedException;
public final void wait(long timeout, int nanos) throwsInterruptedException
public final void wait() throws InterruptedException
注:
1.wait的使用必须要有锁(monitor) ,调用wait()必须在同步代码块中或同步方法里面(synchorinized), 否则会抛异常。
2.sleep()不释放锁。
3.何时wait结束?(1)其他线程调用了该对象的notify方法。(2)其他线程调用了该对象的notifyAll方法。(3)其他线程调用了interrupt中断该线程。(4)时间间隔到了。
9.protected void finalize() throws Throwable 这里会引出垃圾回收
2.haspmap的底层原理,装载因子,扩容?
1.HashMap不是有序的 ,读取不按照你存的,按照哈希值,TreeSet添加的时候自动排序有序,TreeMap和前边一样都是比较器,有序。LinkedHashMap有序,按照输入的形成顺序。
2.HashMap最常用,肯定线程不同步,无锁啊!高效啊
3.只有HashMap键值对是可以用null的。
4.put(key,value)过程(jdk1.8):

1对 Key 求 Hash 值,然后再计算下标
2.如果没有碰撞,直接放入桶中
3.如果碰撞了,以链表的方式链接到后面
4.如果链表长度超过阀值(TREEIFY THRESHOLD==8),就把链表转成红黑树,链表长度低于6,就把红黑树转回链表
5.如果节点已经存在就替换旧值
6.如果桶满了(默认初始容量16*加载因子0.75),就需要 resize(扩容2倍后重排)
5.get(key)过程(1.8):
HashMap 会使用键对象的 hashcode 找到 bucket 位置,找到 bucket 位置之后,会调用 keys.equals() 方法去找到链表中正确的节点,最终找到要找的值对象。
6.计算index=hash&(length-1),与运算更快
hash怎么来的呢hashCode()算出的。
在这里插入图片描述
7.怎么减少碰撞?
得到hash后使用扰动函数减少碰撞。尽量使用不变的,final变量。比如String就是不可变的,而且已经重写了equals和hashCode方法。
8.解决Hash碰撞有哪些方法?
HashMap用的是拉链法。
再哈希法,冲突了就换个hashCode函数再试H1,H2,H3。
建立公共溢出区。
开放寻址法:冲突了就用这个公式再算(p+di)%length,p是初始算出来的H(key),i=1,2,3…根据di有三种方式选择,伪随机,线性探测(1,2,3…),二次探测(1,-1,4,-4,9,-9…两边嘛)
9.为什么不用二叉查找树代替而选择红黑树?为什么不一直使用红黑树?
红黑树是为了解决二叉查找树的缺陷:二叉查找树在特殊情况下会变成一条线性结构,遍历查找会非常慢,红黑树属于平衡二叉树.
如果链表长度很短的话,根本不需要引入红黑树,引入反而会慢。
10.说说你对红黑树的见解?
1.每个节点非红即黑
2.根节点总是黑色的
3.如果节点是红色的,则它的子节点必须是黑色的(反之不一定)
4.每个叶子节点都是黑色的空节点(NIL节点)
从根节点到叶节点或空子节点的每条路径,必须包含相同数目的黑色节点(即相同的黑色高度
在这里插入图片描述
11.扩容:
当一个 Map 填满了75%的 bucket 时候,将会创建原来 HashMap 大小的两倍的 bucket 数组来重新调整 Map 大小,并将原来的对象放入新的 bucket 数组中。这里放入不是直接放!而是再哈希rehashing ,因为长度变了(length-1)&hash,位置和原来不一样咯
12.多线程不用HashMap,用ConcurrentHashMap

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值