Java 哈希表

一、哈希表的由来

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

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

二、哈希表的数据结构

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

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

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

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

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

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

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

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

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

代码实现

主要代码

java 复制代码
/**
 * 定义该类表示一个雇员
 */
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;
    }
}
java 复制代码
/**
 * 定义该类表示链表
 */
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 ++;

        }
    }

}
java 复制代码
/**
 * 该类的主要作用是管理散列表
 */
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);
        }
    }

}

测试类

java 复制代码
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();
    }
}

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

相关推荐
freyazzr41 分钟前
Leetcode刷题 | Day63_图论08_拓扑排序
数据结构·c++·算法·leetcode·图论
一梦浮华1 小时前
自学嵌入式 day 18 - 数据结构 1
数据结构
ai.Neo1 小时前
牛客网NC22015:最大值和最小值
数据结构·c++·算法
范纹杉想快点毕业4 小时前
以项目的方式学QT开发(一)——超详细讲解(120000多字详细讲解,涵盖qt大量知识)逐步更新!
c语言·数据结构·c++·git·qt·链表·github
米粉03054 小时前
算法图表总结:查找、排序与递归(含 Mermaid 图示)
数据结构·算法·排序算法
黑色的山岗在沉睡4 小时前
LeetCode100.4 移动零
数据结构·算法·leetcode
霖004 小时前
PCIe数据采集系统
数据结构·经验分享·单片机·嵌入式硬件·fpga开发·信号处理
敷啊敷衍4 小时前
深入探索 C++ 中的 string 类:从基础到实践
开发语言·数据结构·c++
方博士AI机器人5 小时前
算法与数据结构 - 二叉树结构入门
数据结构·算法·二叉树
{⌐■_■}5 小时前
【redis】redis常见数据结构及其底层,redis单线程读写效率高于多线程的理解,
数据结构·数据库·redis