实现一个最简单的 HashMap|Java面试刷题

303 阅读3分钟

本文正在参加「Java主题月 - Java 刷题打卡」,详情查看 活动链接

一、题目:请实现一个最简单HashMap

我们经常使用HashMap, 经过各个版本的迭代,源代码看起来也是十分的头大

这次我们通过自己实现HashMap来看看,究竟会有哪些东西!

二、代码演示

问题描述

一组 7 个的字符串,需要存放到数组中,要求在获取每个元素的时候时间复杂度是 O(1)。也就是说你不能通过循环遍历的方式进行获取,而是要定位到数组下标直接获取相应的元素。

解决方案

如果说我们需要通过 ID 从数组中获取元素,那么就需要把每个字符串都计算出一个在数组中的位置 ID。字符串获取 ID 你能想到什么方式? 一个字符串最直接的获取跟数字相关的信息就是 HashCode,可 HashCode 的取值范围太大 了[-2147483648, 2147483647],不可能直接使用。那么就需要使用 HashCode 与数组长度做与运算,得到一个可以在数组中出现的位置。如果说有两个元素得到同样的 ID,那么这个数组 ID 下就存放两个字符串。

代码实现
public static void main(String[] args) {
        // 初始化一组字符串
        List<String> list = new ArrayList<>();
        list.add("钢铁侠");
        list.add("浩克");
        list.add("雷神");
        list.add("美国队长");
        list.add("惊奇队长");
        list.add("蜘蛛侠");
        list.add("黑豹");
        // 定义要存放的数组
        String[] tab = new String[8];
        // 循环存放
        for (String key : list) {
            int idx = key.hashCode() & (tab.length - 1); // 计算索引位置
            System.out.println(String.format("key 值=%s Idx=%d", key, idx));
            if (null == tab[idx]) {
                tab[idx] = key;
                continue;
            }
            tab[idx] = tab[idx] + "->" + key;
        }
    }
  1. 初始化一组字符串集合,这里初始化了 7 个。
  2. 定义一个数组用于存放字符串,注意这里的长度是 8,也就是 2 的倍数。这样的数组长度才会出现一个 0111 除高位以外都是 1 的特征,也是为了散列。
  3. 接下来就是循环存放数据,计算出每个字符串在数组中的位置。key.hashCode() & (tab.length - 1)。
  4. 在字符串存放到数组的过程,如果遇到相同的元素,进行连接操作模拟链表的过程。
  5. 最后输出存放结果
测试结果
key 值=钢铁侠 Idx=1
key 值=浩克 Idx=2
key 值=雷神 Idx=7
key 值=美国队长 Idx=7
key 值=惊奇队长 Idx=5
key 值=蜘蛛侠 Idx=5
key 值=黑豹 Idx=0
["黑豹","钢铁侠","浩克",null,null,"惊奇队长->蜘蛛侠",null,"雷神->美国队长"]

三、思考分析

在测试结果首先是计算出每个元素在数组的 Idx,也有出现重复的位置

最后是测试结果的输出,3、4、6,位置是空的 5、7,位置有两个元素被链接起来 惊奇队长->蜘蛛侠 & 雷神->美国队长

这就达到了我们一个最基本的要求,将串元素散列存放到数组中,最后通过字符串元素的索引 ID 进行获取对应字符串。这样是 HashMap 的一个最基本原理,有了这个基础后面就会更容易理解 HashMap 的源码实现。

四、总结

本篇主要是作为开头,了解HashMap的实现原理,接下来会讲到HashMap的散列表与扰动函数 感冒了头疼,HashMap的文章会接着更新,本文主要参考程序员小傅哥的Java面经PDF