从零开始带你学习Java中的数据结构之HashMap

数据结构文章汇总
从零开始带你学习Java中的数据结构之HashMap
从零开始带你学习Java中的数据结构之Queue
从零开始带你学习Java中的数据结构之Stack
从零开始带你学习Java中的数据结构之Arrays/ArrayList
从零开始带你学习Java中的数据结构之List/LinkedList
从零开始带你学习Java中的数据结构之Map
从零开始带你学习Java中的数据结构之Set
从零开始带你学习Java中的数据结构之String,StringBuffer,StringBuild

  今天终于来到我们的重头戏了,想必参加过面试的童鞋一定听过这句话“来说说HashMap的实现原理吧”。那么现在,我就带你来彻底搞通HashMap!

1.jdk1.8-HashMap

  在jdk8版本中,对HashMap有了一个改动。以前的哈希是数组+链表的一个方式构建的,但当表内元素逐步增加时,表的查询效率会大大降低,所以在jdk8中引入了红黑树的概念,当数组长度大于8并且表内元素大于64时,数组+链表的方式会进化为数组+红黑树的方式,红黑树相比于冗长的链表,大大提升了查询效率。

2.HashMap简介

  • 父类:AbstractMap<K,V>
  • 实现的接口:Serializable , Cloneable , Map <K,V>

  HashMap是基于哈希表的 Map 接口的实现。此实现提供所有可选的映射(键值对)操作,并允许使用 null 值和 null 键。(除了非同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。 此实现假定哈希函数将元素适当地分布在各桶之间,可为基本操作(get 和 put)提供稳定的性能。

  键值对的键是唯一的

  假设哈希函数在这些存储桶之间正确分散元素,这个实现为基本操作( get和put )提供了恒定的时间性能。 收集视图的迭代需要与HashMap实例(桶数)加上其大小(键值映射数)的“容量” 成正比 。 因此,如果迭代性能很重要,不要将初始容量设置得太高(或负载因子太低)是非常重要的。

  HashMap的一个实例有两个影响其性能的参数: 初始容量和负载因子 。 容量是哈希表中的桶数,初始容量只是创建哈希表时的容量。 负载因子是在容量自动增加之前允许哈希表得到满足的度量。 当在散列表中的条目的数量超过了负载因数和电流容量的乘积,哈希表被重新散列 (即,内部数据结构被重建),使得哈希表具有桶的大约两倍。

  作为一般规则,默认负载因子(.75)提供了时间和空间成本之间的良好折中。 更高的值会降低空间开销,但会增加查找成本(反映在HashMap类的大部分操作中,包括get和put )。 在设置其初始容量时,应考虑地图中预期的条目数及其负载因子,以便最小化重新组播操作的数量。 如果初始容量大于最大条目数除以负载因子,则不会发生重新排列操作。

  如果许多映射要存储在HashMap实例中,则以足够大的容量创建映射将允许映射的存储效率高于使其根据需要执行自动重新排序以增长表。 请注意,使用同一个hashCode()多个密钥是降低任何哈希表的hashCode()的一种方法。 为了改善影响,当按键是Comparable时,这个类可以使用键之间的比较顺序来帮助打破关系。

3.如何创建HashMap

  • HashMap():用来构造一个HashMap,默认初始容量16,默认负载因子0.75
  • HashMap(int initialCapacity, float loadFactor):用来构造一个HashMap,初始容量initialCapacity,默认负载因子loadFactor

举例:

HashMap<DataType,DataType> map = new HashMap<>();
map.put("abc",2);
map.put("cba",32);
此时打印map值
map={
    
    abc=2, cba=32}
此方法为构造一个默认的HashMap:map,其<K,V>类型分别为DataType,DataType。

4.HashMap常用方法

  • int size()
    返回此地图中键值映射的数量。
  • boolean isEmpty()
    如果此地图不包含键值映射,则返回 true 。
  • get(Object key)
    返回到指定键所映射的值,或null如果此映射包含该键的映射。
    例如:System.out.println(map.get("cba")); 输出为32
  • put(K key, V value)
    将指定的值与此映射中的指定键相关联。
  • boolean containsValue(Object value)
    如果此map将一个或多个键映射到指定值,则返回 true 。
    System.out.println(map.containsValue(4)); 输出的是false
  • Set<Map.Entry<K,V>> entrySet()
    返回此地图中包含的映射的Set视图。
    System.out.println(map.entrySet()); 输出结果为[abc=2, cba=32]
  • Set< K > keySet()
    返回此地图中包含的键的Set视图
    System.out.println(map.entrySet()); 输出结果为[abc, cba]
  • Collection values()
    返回此地图中包含的值的Collection视图。
    System.out.println(map.entrySet()); 输出结果为[2,32]
  • replace(K key, V value)
    只有当目标映射到某个值(value)时,才能替换指定键的条目。
    System.out.println(map.replace("abc",22)); 输出结果为[abc=22, cba=32]
  • remove(Object key)
    从该地图中删除指定键的映射(如果存在)。

猜你喜欢

转载自blog.csdn.net/weixin_40485391/article/details/107617649