jdk1.8比较突出的新特性 ——致敬狂神

函数式接口

一般只包含一个方法声明的接口。(特别的这种接口中可以含有完整的静态方法,和default方法)

新增的四个基本类型函数式接口

  • 函数型 function<S, T> 需要两个泛型分别为入参和返回值
  • 断言型 predicate 会得到一个Boolean型 的结果,
  • 消费型 consumer 只有入参没有返回值
  • 供给型 supplier 只有返回值没有入参

函数式接口,在使用时,都将可以被简化为lambda表达式 一般形式 ()->{}

流式编程

例如

List<User> list = new ArrayList<>();
list.stream()
	.filter(boolean)
	.map()
	.limit(2)
	.sort(Compareable)

集合类,调用stream方法,变成流运算模式,链式编程来对集合中的元素进行各种运算

HashMap

参考https://www.cnblogs.com/coding-996/p/12468618.html

HashMap本质上,是一个node节点的数组,每存储一个k-v就会占用一个node节点。
它在每次存储时都会为每一个节点计算index(数组下标)值。然后存储到计算出的指定位置。
计算方式

n = tab.length;
index = (n - 1) & HashCode(Key);

由于哈希算法很诡异,传入不同的key可能会算出相同的结果(即hash冲突)。所以往HashMap中put值的时候,会有可能发生 正要被存储的 元素 计算出来的节点位置上,已经有元素了! 这时候会去比较 节点上原有的key和 即将被存储的key是否相等,如果相等则直接覆盖掉原节点中的k-v(这个方法有返回值,会把原节点的value值返回),如果不相等则会使用尾插法在这个节点向下形成单链表。

源码写那么复杂,都是在考虑较极端的场景,一直发生hash冲突,在同一个节点位置造成单链表的长度达到8(源码指定的)时,则将单链表转化为红黑树(一种特例的二叉搜索树)

扩容时 会重新计算所有节点的index 为了使元素分布更均匀。
1.8以前,冲突形成单链表时用尾插法,扩容用头插法,这将有可能造成单链表的特例,环! 出现了环时,再获取值就会死循环。
1.8以后均使用尾插法,则链表的指向性保持不变避免了这个问题

初始化的大小为何指定为2的n次方?因为index的计算公式
2的n次方减1 的二进制结果就是 11…1
如 7 为 111
15 为 1111
这时候按位与 & 运算 效率将极其高
因为只与二进制hash值的后几位有关。

加载因子0.75 是综合考虑了 以下两点

  • 降低hash冲突的概率性(泊松分布, 概率为百万分之一)
  • 提高空间利用率(HashMap存储的元素个数达到 初始长度*加载因子时,下一个元素put就会进行扩容了)

未完待续。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值