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 的作用


     


     

  • 相关阅读:
    Posix线程编程指南(3) 线程同步
    Posix线程编程指南(1) 线程创建与取消
    #pragma once
    pycharm中import动态链接库pyd有错误
    vs2013 + python3.52 + boost1.61, 编译C++库失败
    VS2013下的64位与32位程序配置
    首篇
    B . Medal Ranking -UCF Local Programming Contest 2015
    A . Find the Twins -UCF Local Programming Contest 2015
    Restricted RPS CodeForces
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3233662.html
Copyright © 2011-2022 走看看