力争清晰完整准确
1、string类为什么是final的
首先分析string的源码:
public final class string implements java.io.serializable, comparable<string>, charsequence { /** the value is used for character storage. */ private final char value[];
private 限定符,保证string字符串数组的值不可在类外被修改。由于未对外暴露可修改的接口,所以string的值一旦被创建,即不可被修改。
因为字符串是不可修改的(只能读不能写),多个线程可以共享同一个字符串实例
字符串常量池,详情请移步
2、jdk8的hashmap的源码,实现原理,底层结构
hashmap的hash冲突解决,后面单独会写一篇博客。
concurrenthashmap的锁分段,大厂很喜欢问(最近华为电话面试问过我),简单说一句,就是hashmap的数据是一个数组,用多个锁来锁,一个锁锁一个节点的数据链。
不像以前一个锁锁住整个数组,多个线程可分段访问这些数据,自然效率就高了
static class node<k,v> implements map.entry<k,v> { final int hash; final k key; v value; node<k,v> next; node(int hash, k key, v value, node<k,v> next) { this.hash = hash; this.key = key; this.value = value; this.next = next; }
hashmap用 transient node<k,v>[] table 存值,本质上是链表数组(哈希数组+链表+红黑树),是hash散列的,即数组非紧密排列,有空隙,详见下图
图01
为什么有红黑树,看put(新增)的源码片段,如下:
else if (p instanceof treenode) e = ((treenode<k,v>)p).puttreeval(this, tab, hash, key, value);
treenode定义的源码片段,如下:
static final class treenode<k,v> extends linkedhashmap.entry<k,v> { treenode<k,v> parent; // red-black tree links treenode<k,v> left; treenode<k,v> right; treenode<k,v> prev; // needed to unlink next upon deletion boolean red; treenode(int hash, k key, v val, node<k,v> next) { super(hash, key, val, next); }
static final int default_initial_capacity = 1 << 4; // aka 16
默认容量-16。resize时,newcap = oldcap << 1( 2进制,左移1位,即*2,旧的容量翻倍,容量可能不是2的幂,视就又容量情况而定)
public v put(k key, v value) { return putval(hash(key), key, value, false, true); }
1)如果以前这个key有值,put 操作会用新值替换旧值。
2)hash冲突怎么解决
hash(散列),就是key和存储位置有个映射关系f,我们称之为hash函数。hash冲突,就是不同的key,根据hash函数算出来的存储位置相同,后面添加的元素就和原来的hashcode冲突了,所以要重新按照一定规则计算新的存储位置。普通hashmap(java 8的hashmap结构如“图1”,有红黑树)结构如下图:
java8 中的hashmap为了提高查找效率,当链表冲突过高,大于阈值时,会将链表节点转化成红黑树节点
static final float default_load_factor = 0.75f;
load factor默认0.75 ,这个和概率统计有关(hash冲突概率最低),详见
为了减少冲突,当hashmap的数组长度 > 临界值 就会触发扩容,所有元素rehash(重新计算hashcode和存储位置)再放到扩容后的容器中,因为涉及到计算、数据查找、内存拷贝、移动等操作,非常耗时。
临界值 = current capacity * current load factor。默认临界值 = default_initial_capacity * default_load_factor = 16 x 0.75 = 12时,就会触发扩容操作。
*****************************************************************************************************
精力有限,欲望太多,专注做好一件事就行
*****************************************************************************************************
如对本文有疑问, 点击进行留言回复!!
SpringBoot引用阿里easyexcel,Excel导出返回浏览器下载
HashMap、Hashtable、ConcurrentHashMap三者间的异同
解决RecycleView 中Item包含Edittext时,滑动view复用导致数据错乱的问题
多线程、同步工作原理、死锁案例、Lock接口、线程的生命周期的讲解及实现
网友评论