浮点型范围
类型 | 符号位 | 指数位 | 尾数位 |
---|---|---|---|
float | 1bit | 8bits | 23bits |
double | 1bit | 11bits | 52bits |
float因为指数为 0 和 255 代表特殊值。实际浮点数的指数表示范围是1-254,减去偏阶127后得到实际表示范围:-126~+127。
精度丢失
由于我们代码在程序里写的十进制小数,而计算机内部只能用二进制的小数, 所以无法精确的表达。对于二进制小数,小数点右边能表达的值是 1/2, 1/4, 1/8, 1/16, 1/32, 1/64, 1/128 … 1/(2^n)。所有的十进制小数都是这些一点一点的拼凑出来的一个近似的数值, 如1.2(10进制) ≈1.00110011(2进制) = 1 + 1/8+1/16+1/128+1/256 = 1 + 0.19921875。
ArrayList
底层是Object[] elementData数组,默认大小DEFAULT_CAPACITY=10,使用空参构造时只是将默认的空数组赋值给elementData。在添加数据时先执行ensureCapacityInternal(size+1)方法判断容量是否够,先判断elementData是否等于默认空数组,若是,则容量初始化为Math.max(DEFAULT_CAPACITY【默认大小10】, minCapacity【当前所需容量最小大小】);否则若minCapacity大于当前容量,则调用grow方法以1.5倍扩容。
LinkedList
底层是使用静态内部类Node实现的双向链表。
HashMap
底层使用数组+链表/红黑二叉树。桶数组默认长度DEFAULT_INITIAL_CAPACITY是16,负载因子loadFactor默认是0.75,数组长度大于阈值会以两倍形式增长。添加数据哈希冲突时采用尾插法(注:jdk1.7及以前采用头插法,在多线程下可能导致死循环)。当链表的长度大于8,同时桶数组长度大于等于64时,将链表转为红黑二叉树。当桶中元素小于等于6时转为链表。
哈希值计算
1 | static final int hash(Object key) { |
Set
底层直接使用HashMap的key存值。map的value统一存入一个不可变的object对象。
LinkedHashMap
继承HashMap,每个结点在其基础上多了before, after。保证元素的有序性。还可以通过设置accessOrder为true将最近获取的元素移动至链表尾部。可用作简单缓存。也可通过继承自定义removeEldestEntry()方法实现LRU算法实现新增数据时移除最久未使用元素。
HashTable
线程安全。底层使用数组+链表(头插法)。使用synchronized修饰方法。默认容量为11,rehash方法以2倍加1形式扩容。key/value也无法为null。
1 | //hash值直接使用key的hash值 |
TreeMap
底层使用红黑二叉树。初始化时可指定排序规则。
ConcurrentHashMap
key/value都不允许为空。
1.5~1.7前使用分段锁,把Map分成了N个Segment(相当于把Map拆分成N个小的HashTable),put和get的时候,都是现根据key.hashCode()算出放到哪个Segment中,操作不同Segment不会锁冲突。扩容时不会对Segmengt数组增大(默认长度16),只会增加Segmengt 后面的链表容量的大小。即对每个Segmengt 的元素进行的ReHash操作。
1.8后用cas+synchronized。
sizeCtl 定义理解
1 | /** |
这里-N的定义是有问题的,应该取-N对应的二进制的低16位数值为M,此时有M-1个线程进行扩容。
集合相关参考链接
Arrays.sort()
- 排序的是引用类型时
使用的是归并排序(Collections.sort()最终也是调用这方法)。
- 排序的是基本数据类型时
长度小于INSERTION_SORT_THRESHOLD(47):使用插入排序
长度小于QUICKSORT_THRESHOLD(286): 使用快速排序
长度大于286后会先统计其降序子数组数,计数count等于MAX_RUN_COUNT(67)被判断为这个数组不具备 结构(数据时而升时而降),使用快速排序,否则进入归并排序。
枚举(enum)
本质上是一个继承Enum抽象类的final类
反射机制
Java泛型
Java多态实现原理
Java注解
本质上是一个继承Annotation接口的接口
排查Java项目线上运行慢问题
- 使用top查看cpu占有率。
- 使用top -hp pid或ps -mp pid -o THREAD,tid,time查看对应进程的线程使用情况。
- 使用jstat -gcutil pid 【打印间隔时间(默认毫秒)】 【 打印次数】打印Jvm运行时数据区情况。
- 用jstack pid打印该Java进程的堆栈信息。定位对应代码。
响应式编程(Reactive Programming)
响应式编程是一种基于数据流(data stream)和变化传递(propagation of change)的声明式(declarative)的编程范式。
WebFlux框架
JMX
JMX(Java Management Extensions,Java管理扩展)是一个为应用程序植入管理功能的框架。JMX是一套标准的代理和服务,实际上,用户可以在任何Java应用程序中使用这些代理和服务实现管理。