通过优锐课学习笔记分享,我们可以看到HashMap问题在工作面试中很常见。 这也是HashMaps在Java内部如何工作的一些深入说明,分享给大家参考学习。

HashMap在内部如何工作已成为几乎所有访谈中的一个普遍问题。 几乎每个人都知道如何使用HashMap或HashMap与Hashtable之间的区别。 但是,当问题为“ HashMap如何在内部工作?”时,许多人会失败。

这个问题的答案是,它基于哈希原理工作,但听起来并不那么简单。 哈希是一种使用算法将唯一代码分配给变量或属性的机制,从而可以轻松进行检索。 真正的哈希机制在应用于同一对象时应始终返回相同的hashCode()。

然后是一个问题:“哈希如何帮助存储和检索HashMap中的值?” 许多人会说该值将存储在存储桶中,并使用键进行检索。 如果你认为这是有效的,那么你绝对是错误的。 为了证明这一点,让我们看一下HashMap类:

 /**

      * The table, resized as necessary. Length MUST Always be a power of two.

      */

      transient Entry[] table;

那么HashMap中Entry []的用途是什么? HashMap将对象存储为Entry实例,而不是键和值。

什么是入门班?

HashMap有一个称为Entry Class的内部类,其中包含键和值。 还有一个叫做next的东西,稍后您将了解。

 static class Entry<K,V> implements Map.Entry<K,V>

  {

      final K key;

      V value;

      Entry<K,V> next;

      final int hash;

      ........

  }

你知道HashMap将Entry实例存储在数组中,而不是作为键值对存储。 为了存储值,你将使用HashMap的put()方法。 让我们深入研究一下,看看它是如何工作的。

Put()方法如何在内部工作?

该代码将如下所示:

 public V put(K key, V value)

 {

     if (key == null)

        return putForNullKey(value);

     int hash = hash(key.hashCode());

     int i = indexFor(hash, table.length);

     for (Entry<K,V> e = table[i]; e != null; e = e.next)

     {

         Object k;

         if (e.hash == hash && ((k = e.key) == key || key.equals(k)))

          {

              V oldValue = e.value;

              e.value = value;

              e.recordAccess(this);

              return oldValue;

           }

      }

      modCount++;

      addEntry(hash, key, value, i);

      return null;

  }

首先,它检查给定的密钥是否为null。如果给定键为null,则它将存储在零位置,因为null的哈希码将为零。

然后通过调用hashcode方法将哈希码应用于键.hashCode()。为了在数组范围内获得值,调用了hash(key.hashCode()),它对哈希码执行一些移位操作。

indexFor()方法用于获取存储Entry对象的确切位置。

接下来是最重要的部分-如果两个不同的对象具有相同的哈希码(例如Aa和BB将具有相同的哈希码),它将存储在同一存储桶中吗?为了解决这个问题,让我们考虑一下数据结构中的LinkedList。它将具有“下一个”属性,该属性将始终指向下一个对象,与Entry类中的下一个属性指向下一个对象的方式相同。使用这种方法,具有相同哈希码的不同对象将彼此相邻放置。

对于Collision,HashMap检查下一个属性的值。如果为null,则将Entry对象插入该位置。如果下一个属性不为null,则它将保持循环运行,直到下一个属性为null,然后将Entry对象存储在那里。

如何在HashMap中防止重复密钥?

众所周知,HashMap不允许重复键,即使当我们插入具有不同值的相同键时,也仅返回最新值。

 import java.util.HashMap;

 import java.util.Map;

 public class HashMapEg {

  public static void main(String[] args) {

   Map map = new HashMap();

   map.put(1, "sam");

   map.put(1, "Ian");

   map.put(1, "Scott");

   map.put(null, "asdf");

   System.out.println(map);

  }

 }

对于上面的代码,您将获得输出{null = asdf,1 = Scott},因为值sam和Ian将被替换为Scott。 那么,这是怎么发生的呢?

LinkedList中的所有Entry对象将具有相同的哈希码,但是HashMap使用equals()。 此方法检查相等性,因此如果key.equals(k)为true,它将替换Entry类中的值对象而不是键。 这样,可以防止插入重复密钥。

Get()方法如何在内部工作?

将使用put()方法中几乎相同的逻辑来检索值。

 public V get(Object key)

 {

     if (key == null)

        return getForNullKey();

      int hash = hash(key.hashCode());

      for (Entry<K,V> e = table[indexFor(hash, table.length)];e != null;e = e.next)

      {

          Object k;

          if (e.hash == hash && ((k = e.key) == key || key.equals(k)))

              return e.value;

      }

          return null;

  }

 1,First, it gets the hash code of the key object, which is passed, and finds the bucket location.

 2,If the correct bucket is found, it returns the value.

 3,If no match is found, it returns null.

如果两个键具有相同的Hashcode会发生什么?

此处将使用相同的冲突解决机制。 key.equals(k)将一直检查到它为true,如果为true,则返回它的值。

我希望本文能阐明麻烦的HashMap内部机制。 祝大家学习愉快!如有不足之处,欢迎补充评论。

抽丝剥茧,细说架构那些事--优锐课

HashMap如何在Java中工作?的更多相关文章

  1. 如何在JAVA中实现一个固定最大size的hashMap

    如何在JAVA中实现一个固定最大size的hashMap 利用LinkedHashMap的removeEldestEntry方法,重载此方法使得这个map可以增长到最大size,之后每插入一条新的记录 ...

  2. 如何在java中使用sikuli进行自动化测试

    很早之前写过一篇介绍sikuli的文章.本文简单介绍如何在java中使用sikuli进自动化测试. 图形脚本语言sikuli sikuli IDE可以完成常见的单击.右击.移动到.拖动等鼠标操作,ja ...

  3. 如何在Java中调用Python代码

    有时候,我们会碰到这样的问题:与A同学合作写代码,A同学只会写Python,而不会Java, 而你只会写Java并不擅长Python,并且发现难以用Java来重写对方的代码,这时,就不得不想方设法“调 ...

  4. 如何在java中跳出当前多重嵌套循环?有几种方法?

    如何在java中跳出当前多重嵌套循环?有几种方法? - 两种方法   - 1.在外层循环定义标记          ok:          for(int i=0;i<100;i++){    ...

  5. 用代码说话:如何在Java中实现线程

    并发编程是Java语言的重要特性之一,"如何在Java中实现线程"是学习并发编程的入门知识,也是Java工程师面试必备的基础知识.本文从线程说起,然后用代码说明如何在Java中实现 ...

  6. 如何在Java中测试类是否是线程安全的

    通过优锐课的java核心笔记中,我们可以看到关于如何在java中测试类是否线程安全的一些知识点汇总,分享给大家学习参考. 线程安全性测试与典型的单线程测试不同.为了测试一个方法是否是线程安全的,我们需 ...

  7. 如何在 Java 中实现无向环和有向环的检测

    无向环 一个含有环的无向图如下所示,其中有两个环,分别是 0-2-1-0 和 2-3-4-2: 要检测无向图中的环,可以使用深度优先搜索.假设从顶点 0 出发,再走到相邻的顶点 2,接着走到顶点 2 ...

  8. 如何在 Java 中实现最小生成树算法

    定义 在一幅无向图 \(G=(V,E)\) 中,\((u, v)\) 为连接顶点 \(u\) 和顶点 \(v\) 的边,\(w(u,v)\) 为边的权重,若存在边的子集 \(T\subseteq E\ ...

  9. 如何在 Java 中实现 Dijkstra 最短路算法

    定义 最短路问题的定义为:设 \(G=(V,E)\) 为连通图,图中各边 \((v_i,v_j)\) 有权 \(l_{ij}\) (\(l_{ij}=\infty\) 表示 \(v_i,v_j\) 间 ...

随机推荐

  1. 【Java Web开发学习】远程方法调用RMI

    Java RMI 远程方法调用Remote Method Invocation 转载:http://www.cnblogs.com/yangchongxing/p/9078061.html 1.创建远 ...

  2. ConcurrentHashMap比其他并发集合的安全效率要高一些?

    前言 我们知道,ConcurrentHashmap(1.8)这个并发集合框架是线程安全的,当你看到源码的get操作时,会发现get操作全程是没有加任何锁的,这也是这篇博文讨论的问题——为什么它不需要加 ...

  3. Web基础了解版03-jQuery

    jQuery jQuery,顾名思义,也就是JavaScript和查询(Query)极大地简化了JavaScript开发人员遍历HTML文档.操作DOM.处理事件.执行动画和开发Ajax. jQuer ...

  4. 一个非常美的FlutterUI组件扩展集:FLUI

    项目地址 FLUI 官网 下载 Demo APK 体验 这是一个群内的网友写的,感觉里面的组件风格非常美,封装的挺到位的,在此推荐给大家,具体可以参考学习. 可以学到的知识还是挺多的,组件UI封装可以 ...

  5. TP框架对数据库的操作

    1.添加数据       1.1添加一条数据 $user = new User; $user->name = 'thinkphp'; $user->email = 'thinkphp@qq ...

  6. 《Dotnet9》系列之建站-中文站最好WordPress主题,自媒体,博客,企业,商城主题一网打尽

    大家好,我是Dotnet9小编,一个从事dotnet开发8年+的程序员.本文介绍WordPress主题JustNews,本站Dotnet9既是使用WordPress + JustNews主题搭建而成的 ...

  7. 搭建zabbix 4.0

    [root@localhost /]# sed ‐i "s#SELINUX=enforcing#SELINUX=disabled#g" /etc/selinux/config #永 ...

  8. Crow’s Foot Notation

    http://www2.cs.uregina.ca/~bernatja/crowsfoot.html Crow’s Foot Notation A number of data modeling te ...

  9. Java面试题_第四阶段

    1.1 电商行业特点 1.分布式 垂直拆分:根据功能模块进行拆分 水平拆分:根据业务层级进行拆分 2.高并发 用户单位时间内访问服务器数量,是电商行业中面临的主要问题 3.集群 抗击高兵发的有效手段, ...

  10. IT兄弟连 HTML5教程 在移动设备上设置原始大小显示

    在iPhone系列和iPod Touch中使用的是Safari浏览器,它支持前面介绍的媒体查询表达式.例如,使用iPhone 320px×480px的分辨率去访问我们前面的布局示例,却无法得到我们想看 ...