你真的了解哈希表吗?

1. 基本介绍

要了解哈希表,首先就要知道为什么会出现哈希表这个东西,哈希表是用来干什么的?

这就要从数据的访问开始,我们都知道现在网站的数据基本上都是存储在数据库当中,当用户发送请求给服务器的时候,服务器就会从数据库中查询相应的数据而返回给用户,但是有没有想过,当大量用户同时访问数据库会造成什么样的问题呢?很显然,数据库也是有承载限度的,一旦超过了这个限度,数据库将会奔溃,这样将带来严重的后果,并且即使数据库不会奔溃,大量的数据库访问也会拖慢数据库的响应速度,从而降低用户的体验,那有没有什么方法能够解决现在这个问题呢?答案是有,从数据库刚开始出现不就就有人发现了这样的问题,提出了缓存的概念,在数据库和用户之间再套上一层,缓存层,当用户需要访问数据库的时候不是直接查询数据库而是先查询缓存层,如果缓存层没有才会去查询数据库,这样对于一些静态的数据就可以预先加载人缓存,从而提高访问速度,目前常见的缓存产品主要有

  • memcached:分布式缓存的标配
  • Redis:新一代的分布式缓存,有替代memcached的趋势

但是今天要讲的不是这两款,而是哈希表,这是一种数据结构,在早期没有出现缓存产品的时候,哈希表就扮演了缓存这一角色,目前对于少量的数据任然可以使用哈希表来存储将少量访问次数较多的数据存放在哈希表中就可以加快访问的速度,

哈希表的特点

哈希表主要由三部分组成:存储数据的一个类,连接每一个类的一个链表,用来存储链表的一个一维数组

在我看来哈希表的主要实现原理其实还是链表,使用链表将每一个数据类连接起来

哈希表实现图示

image-20220430090614646

其实java也自带了哈希表,例如hashmap,这些的功能和我们将要编写的哈希表的功能是很相似的,之所以手动编写,是为了更好的理解哈希表的工作原理,方便之后我们使用哈希表

哈希表的代码实现

  1. 数据存储单元的编写
class Emp{
    private int id;
    private String name;
    private double salary;
    //有一个指针指向下一个节点
    private Emp next;

    public Emp(int id, String name, double salary) {
        this.id = id;
        this.name = name;
        this.salary = salary;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public Emp getNext() {
        return next;
    }

    public void setNext(Emp next) {
        this.next = next;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", salary=" + salary +
                '}';
    }
}
  1. 连接每一个数据单元链表的编写
class HashTableLink{
    //存在一个头指针指向第一个emp
    private Emp head;
    //添加方法
    public void add(Emp emp){
        //判断头结点是否为空
        if(head == null){
            head = emp;
            return;
        }
        Emp curHead = head;
        while(curHead.getNext() !=null){
            curHead = curHead.getNext();
        }
        //跳出循环说明到链表最后
        curHead.setNext(emp);
    }
    //遍历方法
    public void list(){
        if(head == null){
            System.out.println("表为空,无法遍历");
        }
        Emp curHead = head;
        while(true){
            System.out.println(head);
            if(curHead.getNext()!=null){
                curHead = curHead.getNext();
            }else{
                break;
            }
        }
    }
}
  1. 存储链表的数组编写
class HashTable{
    //创建一个数组用来存储链表
    private HashTableLink[] array;
    int size;
    //初始化数组的大小
    public HashTable(int size) {
        this.size = size;
        array = new HashTableLink[size];
        //初始化数组中的每一个元素,这一点特别重要,否则之后将会出现空指针异常
        for(int i = 0;i<size;i++){
            array[i] = new HashTableLink();
        }
    }
    //编写最后的实现方法
    public int hash(int id){
        return id%size;
    }
    public void add(Emp emp){
        int emplooyNo = hash(emp.getId());
        array[emplooyNo].add(emp);
    }
    public void list(){
        for(int i = 0;i<size;i++){
            array[i].list();
        }
    }
}

测试运行

public class hashTableTest {
    public static void main(String[] args) {
        //通过测试来看看代码的正确性
        HashTable test= new HashTable(2);
        test.add(new Emp(1001,"张三",10000.000));
        test.add(new Emp(1002,"张4",3450000.000));
        test.add(new Emp(1003,"张5",14360000.000));
        test.add(new Emp(1004,"张6",10056400.000));
        test.add(new Emp(1005,"张7",10034300.000));
        System.out.println("=====================");
        test.list();
    }
}


可以看到代码正常运行

💖💖 大家好呀,欢迎来看我的文章😍,不求别的,希望各位大哥哥,小姐姐们能够给我一点点支持,让我这个萌新有前进的动力,同时也欢迎各位大佬给我指出错误,太感谢啦,爱你们😙,哈哈哈💖

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

若离风Adrian

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值