面试之Java基础
hashCode与equals方法重写
public class Test1 {private Long x;private String y;private Integer w;@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Test1 test1 = (Test1) o;return Objects.equals(x, test1.x) && Objects.equals(y, test1.y) && Objects.equals(w, test1.w);}@Overridepublic int hashCode() {return Objects.hash(x, y, w);}
}
== 与equal
== 对比的是栈中的值, 基本数据类型是 变量的值, 引用类型是 对象内存地址。
equals:默认是和==一样, 但是一般都会重写equal方法。
ConcurrentHashMap
HashMap: https://blog.csdn.net/qinwenjng120/article/details/150960136
ConcurrentHashMap:
https://blog.csdn.net/qinwenjng120/article/details/150933009
描述
1.7版本
1. 数据结构:ReetrantLock + Segment +HashEntry
2. get:两次hash, 第一次定位setment, 第二次定位到元素所在的链表的头部,然后通过equal比较。 查询无需加锁,通过volatile保证可见性。
3. put : Segment分段锁,继承ReetrantLock, 锁的粒度是Segment, 其他Segment不受影响。
4. 扩容时,只扩容当前segment内的数组
1.8版本
1. 数据结构:synchronized + CAS + Node + 红黑树
2. get:无锁,Node的val和next都用volatile修饰,保证可见性; 数组用volatile修饰,保证扩容时被读线程感知。
3. put:锁链表的head节点,不影响其他元素的读写,锁的粒度更细;
4. 扩容时,阻塞所有的读写操作,并发扩容。
扩容机制
1.7版本
- ConcurrentHashMap基于Segment分段锁实现
- 每个Segment内部是个小型的HashMap
- 每个Segment扩容,然后转移元素到新的数组中,扩容时数组变成原来的两倍
- 扩容判断的是每个Segment内部独立判断的,判端是否超过阈值。
1.8版本
- 不再基于Segment分段锁实现
- 当某个线程put时,发现ConcurrentHashMap在扩容,则一起进行扩容(支持多线程同时扩容)
- 当某个线程put时,发现ConcurrentHashMap不是在扩容,就将元素放入,然后判断是否超过阈值,超过则进行扩容
- 扩容时,先 生成一个新的数据;先将原数组分组,将每组分给不同的线程来进行元素转移,每个线程负责一组或多组元素的转移。