爪哇2博客
爪哇2博客

哈希图如何在Java中工作

最常见的面试问题是<code>HashMap如何在Java中工作</code>, “如何获取和放置方法 哈希图 内部工作”。在这里,我试图通过一个简单的示例来解释内部功能。 哈希图  是最常用的之一 爪哇中的集合而不是理论,我们将首先从示例开始,这样您将更好地理解,然后我们将了解get()和put()函数如何在 爪哇.

让’举一个非常简单的例子。我有一个 国家  类, we are going to use 国家 类 对象ect 如 键 和 它的 大写字母 (字符串)作为值。下面的示例将帮助您了解如何将这些键值对存储在哈希图中。

1. 国家.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
 
组织.Arpit.爪哇2blog;
上市 国家 {
 
     名称;
     人口;
 
    上市 国家( 名称, 人口) {
        ();
        这个.名称 = 名称;
        这个.人口 = 人口;
    }
    上市 得到Name() {
        返回 名称;
    }
    上市 虚空 setName( 名称) {
        这个.名称 = 名称;
    }
    上市 得到Population() {
        返回 人口;
    }
    上市 虚空 setPopulation( 人口) {
        这个.人口 = 人口;
    }
 
    //如果国家/地区对象的名称长度为偶数,则返回31(任何随机数),如果为奇数,则返回95(任何随机数)。
    //这不是按以下方法生成哈希码的好习惯,但我这样做是为了更好,更轻松地理解哈希图。
    @覆写
    上市 整型 杂凑Code() {
        如果(这个.名称.长度()%2==0)
            返回 31;
        其他
            返回 95;
    }
    @覆写
    上市 布尔值 等于(目的 对象) {
 
        国家 其他 = (国家) 对象;
        如果 (名称.等于IgnoreCase((其他.名称)))
            返回 真正;
        返回 ;
    }
 
}
 

如果您想了解更多关于哈希码和equals对象的方法,可以参考 爪哇中的hashcode()和equals()方法

2. 哈希图Structure.java(主班)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 
进口 爪哇.实用程序.哈希图;
进口 爪哇.实用程序.迭代器;
 
上市 哈希图Structure {
 
    / **
    * @作者Arpit Mandliya
     */
    上市 静态的 虚空 主要([] args) {
 
        国家 印度= 国家(“印度”,1000);
        国家 日本= 国家(“日本”,10000);
 
        国家 法国= 国家(“法国”,2000);
        国家 俄国= 国家(“俄国”,20000);
 
        哈希图<国家, > countryCapitalMap= 哈希图<国家,>();  
        countryCapitalMap.(印度,“德里”);  
        countryCapitalMap.(日本,“东京”);  
        countryCapitalMap.(法国,“巴黎”);  
        countryCapitalMap.(俄国,“莫斯科”);  
 
        迭代器 countryCapitalIter=countryCapitalMap.键Set().迭代器();//将调试点放在这一行  
        (countryCapitalIter.hasNext())  
        {  
            国家 countryObj=countryCapitalIter.下一页();  
             首都=countryCapitalMap.得到(countryObj);  
            系统..打印(countryObj.得到Name()+“ ----”+首都);  
        }  
    }  
 
}
 

现在在第24行放置调试点,然后右键单击项目->debug 如->Java应用程序。程序将在第24行停止执行,然后右键单击 countryCapitalMap  然后选择手表。您将能够看到如下结构。
现在从上图可以看到以下几点
    1. 有一个 条目[]  数组称为表,大小为16。
    2. 该表存储条目类’的对象。 哈希图类具有一个内部类,称为 条目 。该条目具有键值作为实例变量。让’请参见入口类Entry Structure的结构。

1
2
3
4
5
6
7
8
9
10
 
静态的 条目 实施 地图.条目
{
        最后 K ;
        V ;
        条目 下一页;
        最后 整型 杂凑;
        ...//More 码 goes here
}
 

  1. 每当我们尝试将任何键值对放入哈希图中时,实例化Entry类对象的键值并将该对象存储在上述内容中 条目[] (表)。现在您一定想知道,上面创建的Entry对象将存储在哪里(表中的确切位置)。答案是,通过调用Hascode()方法为密钥计算哈希码。该哈希码用于计算上述Entry []表的索引。
  2. 现在,如果您在上图中的数组索引10处看到,它就有一个名为 哈希图$条目 .
  3. We have 放 4 键-values in 哈希图 但似乎只有2个!!!这是因为如果两个对象具有相同的哈希码,则它们将存储在相同的索引处。现在的问题是如何产生的?它以以下形式存储对象 链表 (logically).

So how 哈希码 of above country 键-value pairs are calculated.

1
2
3
4
5
6
 
哈希码 对于 日本 = 95 它的 长度 .
哈希码 对于 印度 =95 它的 长度
哈希码 对于 俄国=31 它的 长度 甚至.
哈希码 对于 法国=31 它的 长度 甚至.
 

下图将清楚地说明LinkedList概念。

所以现在如果您对 哈希图  结构,让我们通过放置和获取方法。


让’看一下put方法的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 
       / **
        *将指定值与该映射中的指定键相关联。如果
         * map previously contained a mapping 对于 the 键, the old 值 是
         * replaced.
         *
         * @param 键
         *            指定值将与之关联的键
         * @param 值
         *            value to be 如sociated with the specified 键
        * @返回与之关联的先前值<tt>key</tt>, or <tt>null</tt>
         *        如果没有映射<tt>key</tt>. (A <tt>null</tt> 返回
         *        也可以指示先前关联的地图
         *         <tt>null</tt> with <tt>key</tt>.)
         */
        上市 V (K , V ) {
            如果 ( == 空值)
                返回 放ForNullKey();
            整型 杂凑 = 杂凑(.杂凑Code());
            整型 i = indexFor(杂凑, .长度);
            对于 (条目 e = [i]; e != 空值; e = e.下一页) {
                目的 k;
                如果 (e.杂凑 == 杂凑 && ((k = e.) == || .等于(k))) {
                    V 旧值 = e.;
                    e. = ;
                    e.recordAccess(这个);
                    返回 旧值;
                }
            }
 
            modCount++;
            addEntry(杂凑, , , i);
            返回 空值;
        }
 

now lets understand above 码 step by step
  1. 检查键对象是否为空。如果key为null,则将其存储在 [0]  because 哈希码 对于 空值 是 always 0.
  2. 关键对象’s 哈希码() 方法被调用并计算哈希码。该哈希码用于查找用于存储Entry对象的数组的索引。有时可能会发生此哈希码函数编写不正确的情况,因此JDK设计人员放置了另一个函数hash(),该函数将高于计算的哈希值作为参数。如果您想了解有关hash()函数的更多信息,可以参考 杂凑map中的hash和indexFor方法.
  3. indexFor(杂凑,.长度)  用于计算表数组中的确切索引以存储Entry对象。
  4. 正如我们在示例中所看到的,如果两个关键对象具有相同的哈希码(称为 碰撞),然后将其以链表的形式存储。因此,在这里,我们将遍历链表。
    • 如果我们刚刚计算出的那个索引上没有元素,那么它将直接把Entry对象放在那个索引上。
    • 如果在该索引处存在元素,则它将迭代直到获得 条目->下一页  as 空值.
    • 如果我们再次输入相同的密钥,从逻辑上讲应该替换旧值该怎么办。是的,它将做到这一点。在迭代时,它将通过调用来检查密钥是否相等 等于()  方法(键.equals(k)),如果此方法返回true,则它将value对象替换为当前Entry’s 值 目的。
    • If it did not find the duplicate 键, then current 条目  对象将成为链表和当前条目中的第一个节点->next将成为该索引上现有的第一个节点。

得到

 让s see implementation of 得到 now:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 
/ **
    *返回指定键所映射到的值,或者{@code 空值}
     * 如果 这个 map contains no mapping 对于 the 键.
     *
     *
    *更正式地说,如果此映射包含从键{@code k}到
    *值{@code v}使得{@code(key == 空值?k == 空值:
    * 键.equals(k))},则此方法返回{@code v};否则返回
     * {@code 空值}. (There can be at most one such mapping.)
     *
     *
    *返回值{@code 空值}不会<i>necessarily</i> indicate that
    *该映射不包含该键的映射;地图也有可能
     * explicitly maps the 键 to {@code 空值}. The {@link #containsKey
    * containsKey}操作可用于区分这两种情况。
     *
    * @请参阅#put(Object,Object)
     */
    上市 V 得到(目的 ) {
        如果 ( == 空值)
            返回 得到ForNullKey();
        整型 杂凑 = 杂凑(.杂凑Code());
        对于 (条目 e = [indexFor(杂凑, .长度)]; e != 空值; e = e.下一页) {
            目的 k;
            如果 (e.杂凑 == 杂凑 && ((k = e.) == || .等于(k)))
                返回 e.;
        }
        返回 空值;
    }
 

当您了解了hashmap的put功能时。因此,了解获取功能非常简单。如果传递任何键以从哈希图获取值对象。
  1. 检查键对象是否为空。如果key为null,则Object的值位于 [0]  将被退回。
  2. 关键对象’s 哈希码() method 是 called 和 杂凑 码 是 calculated.
  3. indexFor(hash,table.length)用于使用生成的哈希码来获取Entry对象来计算表数组中的精确索引。
  4. 在表数组中获取索引后,它将遍历链表并通过调用equals()方法检查键是否相等,如果返回true,则返回Entry对象的值,否则返回null。

记住要点

  • 哈希图 有一个叫做 条目  which stores 键-value pairs.
  • 上面的Entry对象存储在称为table的Entry [](Array)中
  • 表的索引在逻辑上称为存储桶,它存储以下内容的第一个元素: 链表 .
  • 关键对象’s 哈希码()用于查找那个 条目  目的。
  • If two 键 对象ect ‘s have same 哈希码  ,它们将进入相同的表数组存储区。
  • 关键对象‘s 等于()  method 是 used to ensure uniqueness of 键 目的。
  • 价值对象‘完全不使用equals()和hashcode()方法

爪哇 哈希图

请通过  爪哇核心面试题 and 爪哇面试题 了解更多面试问题。

导入联系人

您可能还喜欢:

分享这个

作者

关注作者

相关文章

  • 10月02

    用Java中的值初始化ArrayList

    在本文中,我们将学习使用Java中的值初始化ArrayList。 数组列表是Java中List接口的实现类。它用于存储元素。它基于动态增长的阵列概念。我们可以通过几种方式用值初始化ArrayList。让’我们看到了其中一些…]

  • 3月17日

    爪哇 8中的PriorityQueue

    在本文中,我们将介绍Java 8 PriorityQueue。当应该根据对象的优先级处理对象时,在这种情况下,我们使用PriorityQueue。这是一种特殊的队列(也称为非绑定队列),可以根据元素的自然顺序或基于[…]

  • 10月06日

    2d Arraylist 爪哇示例

    在本文中,我们将看到如何在Java中创建2d Arraylist。创建2d Arraylist的最佳方法是在Java中创建列表的列表。 [crayon-601c9a86e659c088740102 /]让’s创建一个程序来实现2d Arraylist 爪哇。 [crayon-601c9a86e659f866775848 /]输出:list3中的第二个元素:List3_Str2 list1中的第三个元素:List1_Str3 list2中的第一个元素[…]

  • 10月21日

    如何在Java中对HashSet进行排序

    在本文中,我们将看到如何在Java中对HashSet进行排序。 哈希集是一个不按任何顺序存储元素的集合。您可能会遇到需要对HashSet进行排序的情况。排序HashSet的方法有很多种,我们将在这里看到两种方法。使用TreeSet可以使用[…]

  • 10月20日

    要设置的Java数组

    在本文中,我们将学习Java数组设置转换。有很多方法可以将数组转换为set。 1.使用Java 8’s Stream如果您使用的是Java 8,建议您使用此方法。 [crayon-601c9a86e6703605808619 /]输出[John,Martin,Mary] 2.使用HashSet构造函数()我们可以直接调用HashSet‘s的java构造函数set […]

  • 8月10日

    爪哇设置为数组

    在本文中,我们将学习将Java设置为数组转换的方法。有很多方法可以将集合转换为数组。 1.使用Java 8’s Stream如果您使用的是Java 8,建议您使用此方法。 [crayon-601c9a86e67ca847832111 /]输出[John,Martin,Mary] 2.使用toArray()我们可以直接在设置对象上调用toArray方法[…]

发表评论

您的电子邮件地址不会被公开。 必需的地方已做标记 *

订阅我们的新闻

获取质量教程到您的收件箱。现在订阅。


让’s be Friends

©2020 爪哇2博客