浩gg教你学Java(五) ——用HashCode对象排序(简述哈希表)

HashCode对象排序

1.什么是HashCode(简述哈希表)

  哈希表是底层很常用的一种结构,它可以弥补数组的一些不足之处。举个简单的例子: 假设我有10000张卡片,分别放在10000个盒子里面;现在,我想要找出任意一张我想要的卡片,对于数组来说,那我们就得一个盒子一个盒子地遍历,最坏要遍历10000次才能找到。而对于哈希表来说,虽然本质也可以认为是一个数组,但它有一个计算hashcode的hashcode()方法。hashcode()方法是根据一个元素的一些属性,来计算出一个值,可以通过这个值来直接找出元素所在的位置,就像直接用数组下标查询一样。同样是上面卡片的例子: 假如我想要的卡片是红色、菱形、卡面上有3颗星星和一个月亮的图案,我通过hashcode()方法将这几个属性带入进行计算,得到了这张卡片的hashcode值是6200,在没有hash冲突(后面讲) 的情况下,我可以直接找到第6200盒子里就是我想要的卡片,这比数组一个个遍历,快的多得多!
  那么我们也可以大概猜到哈希表的建立方式了。对于每一个元素,我们用hashcode()方法带入这个元素的属性进行计算得到hashcode值,也就是常说的hash key,然后把它放到对应的“盒子”里面;想要找到这个元素,只需要重新计算hashcode,然后到对应的“盒子”里去取即可。
  自然,我们会面临一种特殊的情况,如果两个属性不同的元素,计算出的hashcode相同怎么办?其实这就是hash冲突。 理想情况下,我们认为hash函数(hash函数就是hashcode()方法)设计的非常好,对于任意两个属性不同的元素,我们计算出的hashcode都不一样,这样,每一个“盒子”里都只有一个元素。但实际情况是,hash冲突一般不容易避免,那么我们碰到hash冲突的情况就会使用单链表的结构连接在原有的元素后。举个例子:如果两张卡片A、B计算出的hashcode值都为6200,卡片A先在“盒子”6200中,那么后来的卡片B就会用链表的形式放在卡片A后面:盒子6200->卡片A->卡片B
  了解了hash冲突,我们再次回到原来的卡片问题。如果哈希表发生了hash冲突,我们要快速找到想要的卡片:我们首先计算卡片的hashcode,然后找到他存储的“盒子”,再使用equals()方法对盒子里所有元素一个个比较即可。举个例子,假设盒子60存在关系:盒子60->卡片A->卡片B->卡片C,我们要找卡片C,首先计算卡片C的hashcode值为60,然后使用对象卡片C的equals()方法,来对盒子60里的元素一个个比较,就可以找到。这样也比数组一个个遍历快得多!

2.常见数据类型的hashCode()方法

2.1 整型Integer类

public class TestHashCode {
   
    public static void main (String[] args) {
   
        Integer ix = 1023;//装箱
        System.out.println (ix.hashCode());
    }
}

(不知道装箱的小伙伴可以去看link.)

  • 输出结果:1023
    在这里插入图片描述
    看了下Integer类的hashCode()方法,发现直接返回的就是储存的整型的值。
    在这里插入图片描述

2.2 Object类

public class TestHashCode {
   
    public static void main (String[] args) {
   

        Object obj = new Object();
        System.out.println (obj);
        System
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的基于Java哈希表实现,其中存储了一个静态类 `MyClass`: ```java public class MyHashTable { private static final int TABLE_SIZE = 10; private Entry[] table; public MyHashTable() { table = new Entry[TABLE_SIZE]; for (int i = 0; i < TABLE_SIZE; i++) { table[i] = null; } } public MyClass get(String key) { int hash = (key.hashCode() % TABLE_SIZE); if (table[hash] == null) { return null; } else { Entry entry = table[hash]; while (entry != null && !entry.key.equals(key)) { entry = entry.next; } if (entry == null) { return null; } else { return entry.value; } } } public void put(String key, MyClass value) { int hash = (key.hashCode() % TABLE_SIZE); if (table[hash] == null) { table[hash] = new Entry(key, value); } else { Entry entry = table[hash]; while (entry.next != null && !entry.key.equals(key)) { entry = entry.next; } if (entry.key.equals(key)) { entry.value = value; } else { entry.next = new Entry(key, value); } } } private static class Entry { String key; MyClass value; Entry next; public Entry(String key, MyClass value) { this.key = key; this.value = value; this.next = null; } } private static class MyClass { String name; int age; public MyClass(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "MyClass[name=" + name + ", age=" + age + "]"; } } } ``` 在这个例子中,我们定义了一个 `MyHashTable` 类,其中存储了一个静态类 `MyClass`。哈希表的实现使用了链表来解决哈希冲突的问题。具体来说,每个哈希桶(即哈希表中的一个元素)存储了一个指向链表头的指针,如果多个键被映射到同一个哈希桶中,它们会被存储在同一个链表中。在查找键对应的值时,我们先计算键的哈希值,然后在对应的哈希桶中查找链表,直到找到对应的键为止。在插入键值对时,我们也是先计算键的哈希值,然后在对应的哈希桶中查找链表,如果找到了对应的键,就更新它的值;如果没有找到,就在链表末尾插入一个新的节点。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值