zoukankan      html  css  js  c++  java
  • JAVA学习之HashCode

    public native int hashCode();

    返回该对象的哈希码值。支持此方法是为了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。 

    一、HashCode的作用

      我们通常会用equals判断集合中是否包含一个对象,这种方式需要遍历集合中每一个元素,然后对他们一一进行equals方法比较。对于少量数据的集合该方式自然可以,但当我们的数据很多例如一万个,如果还使用这种逐个遍历的方式显然不合适。于是有人发明了一种哈希算法来提高从集合中查找元素的效率。这种方式的核心就是将集合分为若干个区域,每个对象可以计算出一个哈希码,可以将哈希码分组,每组分别对应某个存储区域,查找对象时我们先根据对象的哈希码来确定该对象存储在某个区域。然后在这个区域内查找元素。

    在java中HashSet、HashMap以及HashTable这些散列集合,就是与hashCode方法一起使用。

    下面这段代码是java.util.HashMap的中put方法的具体实现:

     public V put(K key, V value) {
            if (table == EMPTY_TABLE) {
                inflateTable(threshold);
            }
            if (key == null)
                return putForNullKey(value);
            int hash = hash(key);
            int i = indexFor(hash, table.length);
            for (Entry<K,V> e = table[i]; e != null; e = e.next) {
                Object k;
                if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                    V oldValue = e.value;
                    e.value = value;
                    e.recordAccess(this);
                    return oldValue;
                }
            }
    
            modCount++;
            addEntry(hash, key, value, i);
            return null;
        }

      put方法是用来向HashMap中添加新的元素,从put方法的具体实现可知,会先调用hashCode方法得到该元素的hashCode值,然后查看table中是否存在该hashCode值,如果存在则调用equals方法重新确定是否存在该元素,如果存在,则更新value值,否则将新的元素添加到HashMap中。从这里可以看出,hashCode方法的存在是为了减少equals方法的调用次数,从而提高程序效率。

    二、equals与HashCode

    1、equals与HashCode必须一起出现

    在put()方法中为什么判断HashCode后还要判断equals?

    因为不同的对象可能会生成相同的hashcode值,所以我们不能根据hashcode值判断两个对象是否相等。但是可以直接根据hashcode值判断两个对象不等,如果两个对象的hashcode值不等,则必定是两个不同的对象。如果要判断两个对象是否真正相等,必须通过equals方法。

    所以我们在重写equals方法时一定要重写hashcode方法。因为散列集合在添加数据的时候会先判断对象的hashCode值,hashcode值不同,他们就会被散列在不同的存储区域,所以接下来再比较equals的时候已经没有意义了,这个时候就违背了集合的意义(不允许重复元素的 集合)。

     2、保证集合中的对象的hashcode值不能改变

    当一个对象被存储在散列集合后,就不能修改这个对象中的哪些参与计算哈希值的字段了,否则,对象修改后的哈希值与最初存入集合时的哈希值不相等了,在这中情况中,即使在contains方法使用该对象的当前引用作为参数去散列集合中检索对象,也将出现找不到对象的结果,这将会导致无法从散列集合中单独删除当前对象,从而照成内存溢出。

    使用HashSet演示:

    package com.jalja.org.base.test;
    
    import java.util.HashSet;
    import java.util.Set;
    
    public class Point {
        private int x;
        private int y;
        
        public Point(int x, int y) {
            super();
            this.x = x;
            this.y = y;
        }
        public int getX() {
            return x;
        }
        public void setX(int x) {
            this.x = x;
        }
        public int getY() {
            return y;
        }
        public void setY(int y) {
            this.y = y;
        }
        
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + x;
            result = prime * result + y;
            return result;
        }
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Point other = (Point) obj;
            if (x != other.x)
                return false;
            if (y != other.y)
                return false;
            return true;
        }
        public static void main(String[] args) {
            Point point1=new Point(1,2);
            Point point2=new Point(2,3);
            Point point3=new Point(3,4);
            Set<Point> set=new HashSet<Point>();
            set.add(point1);
            set.add(point2);
            set.add(point3);
            System.out.println(set.size());//3
            point1.setX(5);//改变 point1的x值
            set.remove(point1);//移除 point1
            System.out.println(set.size());//3
        }
    }

    从结果可以看出 point1已经无法删除了。

  • 相关阅读:
    数学之美(吴军著)学习总结和经典摘抄
    【翻译自mos文章】Oracle GoldenGate 怎么在源头的传输进程和目的端的server/collector进程之间分配 port?
    atitit.浏览器插件解决方式----ftp插件 attilax 总结
    Libgdx: android单机斗地主支持局域网wifi联网的网络模块核心代码
    毕业前的五味杂陈
    Online Object Tracking: A Benchmark 论文笔记
    开源前夕先给大家赞赏一下我用C语言开发的云贴吧 站点自己主动兼容-移动、手机、PC自己主动兼容云贴吧
    JVM —— Java 对象占用空间大小计算
    Python之爬虫-京东商品
    Python之游戏开发-飞机大战
  • 原文地址:https://www.cnblogs.com/jalja/p/6525443.html
Copyright © 2011-2022 走看看