详解HashMap集合(12)


b:如果后续节点是链表节点 , 则通过循环遍历链表根据key获取value
2.上述红黑树节点调用的是getTreeNode方法通过树形节点的find方法进行查找:
final TreeNode getTreeNode(int h, Object k) {return ((parent != null) ? root() : this).find(h, k, null); } final TreeNode find(int h, Object k, Class kc) {TreeNode p = this;do {int ph, dir; K pk;TreeNode pl = p.left, pr = p.right, q;if ((ph = p.hash) > h)p = pl;else if (ph < h)p = pr;else if ((pk = p.key) == k || (k != null //找到之后直接返回else if (pl == null)p = pr;else if (pr == null)p = pl;else if ((kc != null ||(kc = comparableClassFor(k)) != null)//递归查找else if ((q = pr.find(h, k, kc)) != null)return q;elsep = pl;} while (p != null);return null;}3.查找红黑树 , 由于之前添加时已经保证这个树是有序的了 , 因此查找时基本就是折半查找 , 效率更高 。
4.这里和插入时一样 , 如果对比节点的哈希值和要查找的哈希值相等 , 就会判断key是否相等 , 相等就直接返回 。 不相等就从子树中递归查找 。
5.
若为树 , 则在树中通过key.equals(k)查找 , O(logn)
若为链表 , 则在链表中通过key.equals(k)查找 , O(n) 。
4.3.6遍历HashMap集合几种方式1、分别遍历Key和Values
2、使用Iterator迭代器迭代
3、通过get方式(不建议使用)
说明:根据阿里开发手册 , 不建议使用这种方式 , 因为迭代两次 。 keySet获取Iterator一次 , 还有通过get又迭代一次 。 降低性能 。
4.jdk8以后使用Map接口中的默认方法:
default void forEach(BiConsumer action) BiConsumer接口中的方法: void accept(T t, U u) 对给定的参数执行此操作 。参数t - 第一个输入参数u - 第二个输入参数 遍历代码:
public class Demo02 {public static void main(String[] args) {HashMap m1 = new HashMap();m1.put("001", "zhangsan");m1.put("002", "lisi");m1.forEach((key,value)->{System.out.println(key+"---"+value);});}}5.如何设计多个非重复的键值对要存储HashMap的初始化?5.1HashMap的初始化问题描述如果我们确切的知道我们有多少键值对需要存储 , 那么我们在初始化HashMap的时候就应该指定它的容量 , 以防止HashMap自动扩容 , 影响使用效率 。
默认情况下HashMap的容量是16 , 但是 , 如果用户通过构造函数指定了一个数字作为容量 , 那么Hash会选择大于该数字的第一个2的幂作为容量 。 (3->4、7->8、9->16) .这点我们在上述已经进行过讲解 。
《阿里巴巴Java开发手册》中建议我们设置HashMap的初始化容量 。
那么 , 为什么要这么建议?你有想过没有 。
当然 , 以上建议也是有理论支撑的 。 我们上面介绍过 , HashMap的扩容机制 , 就是当达到扩容条件时会进行扩容 。 HashMap的扩容条件就是当HashMap中的元素个数(size)超过临界值(threshold)时就会自动扩容 。 在HashMap中 , threshold = loadFactor * capacity 。
所以 , 如果我们没有设置初始容量大小 , 随着元素的不断增加 , HashMap会有可能发生多次扩容 , 而HashMap中的扩容机制决定了每次扩容都需要重建hash表 , 是非常影响性能的 。
但是设置初始化容量 , 设置的数值不同也会影响性能 , 那么当我们已知HashMap中即将存放的KV个数的时候 , 容量设置成多少为好呢?
5.2HashMap中容量的初始化当我们使用HashMap(int initialCapacity)来初始化容量的时候 , jdk会默认帮我们计算一个相对合理的值当做初始容量 。 那么 , 是不是我们只需要把已知的HashMap中即将存放的元素个数直接传给initialCapacity就可以了呢?


推荐阅读