zoukankan      html  css  js  c++  java
  • java--map容器的hashcode和equals

    先看一个例子

    首先定义一个user类。

    package com.text.tool;
    
    
    public class User {
    	int id;
    
    	User(int id) {
    		this.id = id;
    	}
    
    	public String toString() {
    		return "key="+id;
    	}
    }
    


    其次写一个测试类,创建一个HashMap,在map中User对象作为KEY。

    package com.text.tool;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class TestMap {
    
    	public static void main(String[] args) {
    		Map map = new HashMap();
    		map.put(new User(1), 1);
    		map.put(new User(2), 1);
    		map.put(new User(3), 1);
    		
    		System.out.println(map.keySet());
    		System.out.println(map.get(new User(1))
    	}
    }
    
    


    输出结果,让人疑惑的是为什么MAP数组中匹配不到new User(1)。

    [key=1, key=2, key=3]
    null

    我们可以简单看下HashMap源码,在源码中获取到key对应value做了一个判断,e.hash == hash && eq(k, e.key)也就是对key的hashcode进行比对,以及进行equals判断。

    我们传入的对象User默认继承Object,所以equals及hashCode默认是Object的方法,而此时这里的equals比较的是两个对象的内存中的地址并非value,所以第二个new User(1)就无法再MAP数组中取到value了。

        public Object get(Object key) {
            Object k = maskNull(key);
            int hash = hash(k);
            int i = indexFor(hash, table.length);
            Entry e = table[i]; 
            while (true) {
                if (e == null)
                    return e;
                if (e.hash == hash && eq(k, e.key)) 
                    return e.value;
                e = e.next;
            }
        }
        public boolean equals(Object obj) {
    	return (this == obj);
        }
        public native int hashCode();


    在User类中重写equals及hashcode方法,在启用main方法就不会有问题了。

    package com.text.tool;
    
    
    public class User {
    	int id;
    
    	User(int id) {
    		this.id = id;
    	}
    
    	public String toString() {
    		return "key="+id;
    	}
    	
    	public int hashCode() {
    		return id;
    	}
    
    	public boolean equals(Object o) {
    		return o instanceof User && (id == ((User) o).id);
    	}
    }
    

    执行MAIN方法输出结果:

    [key=2, key=1, key=3]
    1
    


    截取think in java一段描述:

     


    equals()相等的两个对象,hashcode()一定相等; 
    equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。换句话说,equals()方法不相等的两个对象,hashcode()有可能相等。(我的理解是由于哈希码在生成的时候产生冲突造成的)。 
    反过来:hashcode()不等,一定能推出equals()也不等;hashcode()相等,equals()可能相等,也可能不等。解释下第3点的使用范围,我的理解是在object、String等类中都能使用。在object类中,hashcode()方法是本地方法,返回的是对象的地址值,而object类中的equals()方法比较的也是两个对象的地址值,如果equals()相等,说明两个对象地址值也相等,当然hashcode()也就相等了;在String类中,equals()返回的是两个对象内容的比较,当两个对象内容相等时, 
    Hashcode()方法根据String类的重写代码的分析,也可知道hashcode()返回结果也会相等。以此类推,可以知道Integer、Double等封装类中经过重写的equals()和hashcode()方法也同样适合于这个原则。当然没有经过重写的类,在继承了object类的equals()和hashcode()方法后,也会遵守这个原则。

    附下哈希表结构:

     


    在一个数组中存储对象时,通过 hashCode 得到的哈希值来计算数组的索引位置(通常是求余运算),然后根据这个索引位置进行存取。多个对象计算出来的索引位置相同(叫hash冲突)时,用链表保存。冲突怎么保证取到的就是自己呢?那么就要用到 Object.equals() 方法。

    所以要把对象存储在像 hash table类似的数据结构(比如:HashSet)中,hashCode 与 equals 要成对实现。

    部分内容来源:

    java中hashcode()和equals()的详解

    hashcode 的作用


     


     

  • 相关阅读:
    SuperMap房产测绘成果管理平台
    SuperMap产权登记管理平台
    Android adb shell am 的用法(1)
    由浅入深谈Perl中的排序
    Android 内存监测和分析工具
    Android 网络通信
    adb server is out of date. killing...
    引导页使用ViewPager遇到OutofMemoryError的解决方案
    adb logcat 详解
    How to send mail by java mail in Android uiautomator testing?
  • 原文地址:https://www.cnblogs.com/aukle/p/3235482.html
Copyright © 2011-2022 走看看