Java 哈希表

news2025/1/16 17:57:44

一、哈希表的由来

我们的java程序通过访问数据库来获取数据,但是当我们对数据库所查询的信息进行大量分析后得知,我们要查询的数据满足二八定律,一般数据库的数据基本存储在磁盘当中。这使得每次查询数据将变得无比缓慢。为此我们可以将经常查询的数据放置在内存当中,在内存当中设置缓存,我们java程序先去缓存当中去查询数据,这样将大大节省我们的数据查询时间。

缓存可以分为两种一种是市面上的存储产品,例如redis.也或者我们自己可以开发一个缓存(哈希表)。

二、哈希表的数据结构

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

散列函数:是用来确定我们每一个值得存储在哪一个链表之上。

三、为了了解什么是哈希表

我们先来看如下的一道题:

有一个公司,当有新的员工来报道时,需要将该员工的信息加入(id,性别,年龄,住址,...),当输入该用户id时,需要查询到该员工的所有信息。

要求:不使用数据库,尽量节省内存,速度越快越好 --> 哈希表

分析清楚上边的题以后我们来用代码将其实现。

首先分析这个代码有哪些组成。

根据拆分我们可以知道一个哈希表是由节点组成链表,每一个链表都存放在数据当中的每个节点当中,如下图。

代码实现

主要代码

/**
 * 定义该类表示一个雇员
 */
public class Employee {
    public int id;
    public String name;
    public Employee next; // next默认为空
    //定义构造函数
    public Employee(int id, String name) {
        this.id = id;
        this.name = name;
    }
}
/**
 * 定义该类表示链表
 */
public class EmpLiskedList {
    // 定义头指针,指向第一个Emp对象
    public Employee head;

    /**
     * 添加雇员到链表
     * 说明:
     * 我们这个方法采用的是尾插法将新插入的数据放置到尾部
     * 1.判断头指针是否为空
     * 2.如果不是第一个雇员,则使用一个辅助指针,帮助定位到最后
     * @param employee
     */
    public void add(Employee employee){
        //判断头指针是否为空
        if(head == null){
            head = employee;
            return;
        }
        //如果不是第一个雇员,则使用一个辅助指针,帮助定位到最后
        Employee tempEmp = head;
        while (true){
            if(tempEmp.next == null){ //说明链表到了最后
                break;
            }
            tempEmp = tempEmp.next; //后移
        }
        //将employee加入到链表
        tempEmp.next = employee;
    }

    /**
     * 遍历链表的雇员信息
     * 说明:
     * 1. 首先需要判断链表是否为空
     * 2. 借助辅助指针进行遍历
     * @param i 这是第几条链表
     */
    public void list(int i){
        if(head == null){ // 说明链表为空
            System.out.println("链表为空");
            return;
        }
        //定义一个值表示链表的大小和
        int count = 1;
        //定义辅助指针
        Employee tempEmp = head;
        while (true){
            System.out.println("id:="+tempEmp.id+" "+"name:="+tempEmp.name);
            //判断是否到了最后节点
            if(tempEmp.next == null){
                System.out.println("这是第"+i+"条链表,长度为"+count);
                break;
            }
            tempEmp = tempEmp.next;//后移
            count ++;

        }
    }

}
/**
 * 该类的主要作用是管理散列表
 */
public class HashTab {
    // 定义散列表
    private EmpLiskedList[] empLiskedListArray;

    //定义散列表的大小
    private int size;

    // 构造器
    public HashTab(int size){
        this.size = size;
        //初始化empLiskedListArray
        empLiskedListArray = new EmpLiskedList[size];
        // 一个小坑,这个地方不要忘记分别初始化每个链表,
        // 我们的散列表当中每个位置还是空的
        for (int i=0;i<size;i++){
            empLiskedListArray[i] = new EmpLiskedList();
        }

    }

    //编写散列函数,使用一个简单取模法
    public int hash(int id){
        return id % size;
    }

    // 添加雇员
    public void add(Employee employee){
        //根据员工的id,得到该员工应该添加到那一条链表
        int num = hash(employee.id);
        // 将emp添加到对应的链表当中去
        empLiskedListArray[num].add(employee);

    }

    //遍历所有的链表,遍历hashtable
    public void list(){
        for (int i=0;i<size;i++){
            empLiskedListArray[i].list(i);
        }
    }

}

测试类

public class Test {
    public static void main(String[] args) {
        HashTab hashTab = new HashTab(8);
        Employee employee1 = new Employee(1,"张三1");
        Employee employee2 = new Employee(4,"张三4");
        Employee employee3 = new Employee(6,"张三6");
        Employee employee4 = new Employee(8,"张三8");
        Employee employee5 = new Employee(10,"张三10");
        Employee employee6 = new Employee(11,"张三11");
        Employee employee7 = new Employee(15,"张三15");
        Employee employee8 = new Employee(16,"张三16");
        Employee employee9 = new Employee(18,"张三18");
        Employee employee10 = new Employee(20,"张三20");

        hashTab.add(employee1);
        hashTab.add(employee2);
        hashTab.add(employee3);
        hashTab.add(employee4);
        hashTab.add(employee5);
        hashTab.add(employee6);
        hashTab.add(employee7);
        hashTab.add(employee8);
        hashTab.add(employee9);
        hashTab.add(employee10);

        hashTab.list();
    }
}

 谢谢你的阅读,点个赞吧!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1572554.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

怎么查看DevV++调试过程中变量的值

方法一&#xff1a;将鼠标移动到代码变量的上方&#xff0c;就会显示当前变量的值 方法二&#xff1a;视图->浮动报告窗口->出现调试窗口 点击下面添加查看输入你想要看的变量就可以在调试窗口显示出来了 如果有帮助就点个赞在走呗

【MySQL】如何判断一个数据库是否出问题

在实际的应用中&#xff0c;其实大多数是主从结构。而采用主备&#xff0c;一般都需要一定的费用。 对于主备&#xff0c;如果主机故障&#xff0c;那么只需要直接将流量打到备机就可以&#xff0c;但是对于一主多从&#xff0c;还需要将从库连接到主库上。 对于切换的操作&a…

一站式指南:Flutter应用如何顺利登陆苹果App Store

引言 &#x1f680; Flutter作为一种跨平台的移动应用程序开发框架&#xff0c;为开发者提供了便利&#xff0c;使他们能够通过单一的代码库构建出高性能、高保真度的应用程序&#xff0c;同时支持Android和iOS两个平台。然而&#xff0c;完成Flutter应用程序的开发只是第一步…

Ubuntu部署LangChain-Chatchat

个人博客&#xff1a;https://blog.lukeewin.top 更多内容欢迎访问我的博客。 一、环境 OS: Ubuntu 20.04 PyTorch: 2.0.0 Python: 3.8 CUDA: 11.8 GPU: RTX 4090 24GB CPU: 12 vCPU Intel(R) Xeon(R) Platinum 8352V CPU 2.10GHz RAM: 90GB 硬盘: 180GB LLM: Chatglm3-6b E…

008 CSS盒子模型

文章目录 盒子模型内容-宽度和高度内边距-padding边框-border圆角-border-radius 外边距-margin上下margin的传递上下margin的折叠块级元素的水平居中行内级元素(包括inline-block元素)的水平居中 外轮廓-outline盒子阴影-box-shadow文字阴影-text-shadow行内非替换元素的特殊性…

C语言实现快速排序算法

1. 什么是快速排序算法 快速排序的核心思想是通过分治法&#xff08;Divide and Conquer&#xff09;来实现排序。 算法的基本步骤是: 1. 选择一个基准值&#xff08;通常是数组中的某个元素&#xff09;&#xff0c;将数组分成两部分&#xff0c;使得左边的部分所有元素都小于…

文心一言指令词宝典之营销文案篇

作者&#xff1a;哈哥撩编程&#xff08;视频号、抖音、公众号同名&#xff09; 新星计划全栈领域优秀创作者博客专家全国博客之星第四名超级个体COC上海社区主理人特约讲师谷歌亚马逊演讲嘉宾科技博主极星会首批签约作者 &#x1f3c6; 推荐专栏&#xff1a; &#x1f3c5;…

Linux:IO多路转接之poll

文章目录 select的缺点pollstruct pollfd解决缺点的方式 代码实现 本篇总结的是poll的相关内容&#xff0c;在总结poll的内容前&#xff0c;先回顾一下select的缺点 select的缺点 select的缺点也比较明显 等待的fd是有上限的&#xff0c;在我们当前这个版本来说&#xff0c;…

Hive 之 UDF 运用(包会的)

文章目录 UDF 是什么&#xff1f;reflect静态方法调用实例方法调用 自定义 UDF&#xff08;GenericUDF&#xff09;1.创建项目2.创建类继承 UDF3.数据类型判断4.编写业务逻辑5.定义函数描述信息6.打包与上传7.注册 UDF 函数并测试返回复杂的数据类型 UDF 是什么&#xff1f; H…

【Redis教程0x0F】Redis实战篇

Redis如何实现延迟队列&#xff1f; 延迟队列是指把当前要做的事情&#xff0c;往后推迟一段时间再做。延迟队列的常见使用场景有以下几种&#xff1a; 在淘宝、京东等购物平台上下单&#xff0c;超过一定时间未付款&#xff0c;订单会自动取消&#xff1b;打车的时候&#x…

Android中的aidl接口及案例说明

目录 一、什么是AIDL 二、AIDL语法规格 三、AIDL实例 客户端: 服务端: 一、什么是AIDL AIDL,即 Android Interface Definition Language,用于android不同进程间通信接口。同一个应用里面还是建议用正常接口实现功能即可。 官方说明:Android 接口定义语言 (AIDL) | …

150行Python代码模拟太阳系行星运转

今天我们用Python来模拟一下太阳系行星运动轨迹~ 先上成品图&#xff08;运行效果含音乐的呦&#xff09; 想要实现这样的效果并不难 准备材料 首先我们需要准备这样一些材料 宇宙背景图 背景透明的行星图 编写代码 代码分块详解 导入需要的模块 import pygame import …

高效学习方法:冥想背诵,看一句念一句,再每个词分析位置及语法等合理性,忘记哪个词再看猜下为什么会忘,跟自己的表达哪里不一样。

原则&#xff1a;易学则易行&#xff0c;则效果最好。《易经》 你提到的这种学习方法结合了多种记忆和理解技巧&#xff0c;可以帮助提高学习效率。下面是对这种方法的一个详细解释和一些建议&#xff1a; 冥想背诵&#xff1a;通过冥想来集中注意力&#xff0c;可以帮助你在没…

redis 数据库的安装及使用方法

目录 一 关系数据库与非关系型数据库 &#xff08;一&#xff09;关系型数据库 1&#xff0c;关系型数据库是什么 2&#xff0c;主流的关系型数据库有哪些 3&#xff0c;关系型数据库注意事项 &#xff08;二&#xff09;非关系型数据库 1&#xff0c;非关系型数据库是…

WLAN组网经典实验

1、项目需求 现有一无线网络建设,需求为三层组网,AP、STA网关均在核心交换机上,AC作为给AP分配IP地址的DHCP,SW1作为给STA分配IP地址的DHCP,默认AP工作在vlan1上,说白了就是管理vlan流量在AC上跑,业务vlan流量在核心上跑。 2、项目规划 如上图所示: AP1管理vlan: 2 …

Unity性能优化篇(十四) 其他优化细节以及UPR优化分析器

代码优化&#xff1a; 1. 使用AssetBundle作为资源加载方案。 而且经常一起使用的资源可以打在同一个AssetBundle包中。尽量避免同一个资源被打包进多个AB包中。压缩方式尽量使用LZ4&#xff0c;少用或不要用LZMA的压缩方式。如果确定后续开发不会升级Unity版本&#xff0c;则可…

基于SpringBoot+Vue的前后端分离的电影院售票管理运营平台

一、项目背景介绍&#xff1a; 该系统研究背景聚焦于电影市场的快速增长、互联网电影院管理、用户体验和服务优化以及数据管理与决策支持。随着人们生活水平的提高&#xff0c;电影观影已成为重要的娱乐方式&#xff0c;电影院作为传统场所面临新的挑战。借助SpringBootVue技术…

vscode的源码插件GitHub Repositories

打铁还需自身硬&#xff0c;需要不断提升自我&#xff0c;提升自我的一种方式就是看源码&#xff0c;站在更高的维度去理解底层原理&#xff0c;以便以后更好的开发和解决问题&#xff0c;由于源码一个动不动就是几个G甚至十几个G&#xff0c;如果一个个源码下载下来&#xff0…

NLP在搜索召回领域中的应用场景

自然语言处理&#xff08;NLP&#xff09;在搜索召回领域中的应用场景非常广泛&#xff0c;它通过理解和分析人类语言&#xff0c;提高了信息检索的准确性和效率。以下是一些具体的应用场景&#xff1a; 1. 搜索引擎优化 NLP技术可以用于优化搜索引擎的查询处理&#xff0c;通…

江协科技STM32:TIM输出比较

输出比较模块的主要功能&#xff1a;输出一定频率和占空比的PWM波形 CC是捕获比较的意思,R是Register&#xff0c;寄存器的意思&#xff0c;CCR捕获比较寄存器它是输入捕获和输出比较共用的 当使用输入捕获&#xff0c;它就是捕获寄存器 当使用输出比较&#xff0c;它就是比…