【个人总结】HashMap使用过程中遇到的坑

HashMap

所谓HashMap是Map基于哈希表的实现,通过键值的哈希值映射到内存的一个位置进行存储,从而实现在O(1)复杂度下的搜索。可见,其性能是相当可观的,在大规模数据下速度比普通的对比查找快了许多倍。因而是很多数据存储的优先选择。
另外,HashMap还有线程安全的、不可修改的以及线性的等多种衍生。

踩坑记录

在一个实验中需要存储一个类和其对应的下标,因为设计原因,需要将这个类的对象作为键值。基于HashMap良好的特性,故尝试用HashMap来实现。
但出现了一个问题,将数据put(obj, number)后,再get(obj)就一直等于null,实在令人匪夷所思。以为又遇到了什么神奇的BUG。
但找BUG的过程中,惊奇的发现HashMap本身的size是正确的,也就说put成功了,那为什么找不到值呢?

解决问题

仔细考虑了一下,结合HashMap的实现,它是通过obj的HashCode进行存储的,也是通过这个来进行查找。如果找不到,只能说明其HashCode的变了。
果然,obj实例化的类是mutable类型,并且在put进去后,代码中果然有修改其字段的逻辑。
也就是说,obj在put到map以后,其HashCode发生了改变,所以再回去找的时候便找不到了。

    /**
     * Override equals.
     * @return if they equal to each other
     */
    @Override
    public boolean equals(final Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Monkey monkey = (Monkey) o;
        return id == monkey.id && direction == monkey.direction
                && maxVelocity == monkey.maxVelocity
                && velocity == monkey.velocity
                && age == monkey.age
                && Objects.equals(chooser, monkey.chooser);
    }

    /**
     * Override hashcode.
     * @return hashCode of the monkey
     */
    @Override
    public int hashCode() {
        return Objects.hash(id, direction, maxVelocity, velocity, chooser, age);
    }

难道mutable类型就不能使用HashMap吗?
显然不是,具体到我的使用中,其id是唯一且不变的,拿它重载HashCode便解决了这个问题。

    /**
     * Override hashcode.
     *
     * @return hashCode of the monkey
     */
    @Override
    public int hashCode() {
        return Objects.hash(id);
    }

经过测试,果然能够正常get到了。

总结

使用HashCode时一定要注意key是否是mutable的,一定要注意其HashCode的设定。

发布了75 篇原创文章 · 获赞 28 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Swocky/article/details/92771704