zoukankan      html  css  js  c++  java
  • 为什么重写equals()就必须重写hashCode(),什么情况下可以不重写hashCode()

      (1)当所在类不使用HashSet、Hashtable、HashMap等散列集合进行存储的时候,可以不使用hashcode。

      (2)当在HashSet、Hashtable、HashMap中使用该类时,hashcode和equals是有关系的,hashcode和equals需要同时重写才能保证元素的唯一性。hashcode是为了提高散列结构存储中查找的效率,在线性表中没有作用。

      ==操作符比较的是值【变量(栈)内存中存放的对象的(堆)内存地址】。

      equal用于比较两个对象的值是否相同【不是比地址】。

      注意:Object类中的equals方法和“==”是一样的,没有区别,而String类,Integer类等一些类,是重写了equals方法,才使得equals和“==不同”。对于基础数据类型来说,没有重写equals方法,故两者是一样。

    ①equals()方法:

    public class BaseTypeDemo {
        public static void main(String[] args) {
            //对于基本类型的变量。"=="和"equal"的区别
            int t1=57;
            int t2=67;
            int t3=124;
            int t4=124;
            //“==”对于基本数据类型,判断两个变量的值是否相等。
            Boolean result1=(t1==t2);
            Boolean result2=((t1+t2)==t3);
            Boolean result3=(t3==t4);
            System.out.println("【t1==t2】"+result1);
            System.out.println("【(t1+t2)=t3】"+result2 );
            System.out.println("【t3=t4】"+result3);
     
            //“equal”不能用于基本数据类型。只能用于类变量。对于基本数据类型要用其包装类。
            Integer i1=new Integer(t1);
            Integer i2=new Integer(t2);
            Integer i3=new Integer(t3);
            Integer i4=new Integer(t4);
     
     
            Boolean ri1=i1.equals(i2);
            Boolean ri2=i3.equals(i1+i2);
            Boolean ri3=i3.equals(i4);
     
            System.out.println("【i1.equals(i2)】"+ri1);
            System.out.println("【i3.equals(i1+i2)】"+ri2);
            System.out.println("【i3.equals(i4)】"+ri3);
        }
    }
    /**
    *运行结果
    【t1==t2】false
    【(t1+t2)=t3】true
    【t3=t4】true
    【i1.equals(i2)】false
    【i3.equals(i1+i2)】true
    【i3.equals(i4)】true
    */
    

      String类,是重写了equals方法,才使得equals和“==不同”。让equals比较的值,==比较的引用地址。

    public class StringDemo {
        public static void main(String[] args) {
            String str1 = "Hello";
            String str2 = new String("Hello");
            String str3 = str2; // 引用传递
            System.out.println(str1 == str2); // false
            System.out.println(str1 == str3); // false
            System.out.println(str2 == str3); // true
            System.out.println(str1.equals(str2)); // true
            System.out.println(str1.equals(str3)); // true
            System.out.println(str2.equals(str3)); // true
        }
    }
    

      重写equals()方法时需要把类的字段的那些在实际对象中进行传入比较,保证是比较的对象的“内容”。而如果不重写此时的hashCode()的话,就会出现如果是相同的一个对象,但是我修改了这个对象的某个属性,比如在hashMap中保存的这个对象,但是此时我再想get到它就只能返回一个空值null了,因为hash值是与对象的字段属性相关联的,此时由于修改了这些字段属性,所以对应的对象的哈希值也发生了改变,再用此时的哈希值去取对象是取不到的。

      

    package map.test;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class Person {
    	private String name;
    	private int age;
    
    	public Person() {
    		super();
    	}
    
    	public Person(String name, int age) {
    		super();
    		this.name = name;
    		this.age = age;
    	}
    
    	// 测试hashCode
    //    @Override
    //    public boolean equals(Object obj) {
    //        // TODO Auto-generated method stub
    //        return true;
    //    }
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public int getAge() {
    		return age;
    	}
    
    	public void setAge(int age) {
    		this.age = age;
    	}
    
    	@Override
    	public int hashCode() {
    		final int prime = 31;
    		int result = 1;
    		result = prime * result + age;
    		result = prime * result + ((name == null) ? 0 : name.hashCode());
    		return result;
    	}
    
    	/*
    	 * (non-Javadoc)
    	 * 
    	 * @see java.lang.Object#equals(java.lang.Object)
    	 */
    	@Override
    	public boolean equals(Object obj) {
    		if (this == obj)
    			return true;
    		if (obj == null)
    			return false;
    		if (getClass() != obj.getClass())
    			return false;
    		Person other = (Person) obj;
    		if (age != other.age)
    			return false;
    		if (name == null) {
    			if (other.name != null)
    				return false;
    		} else if (!name.equals(other.name))
    			return false;
    		return true;
    	}
    
    	public static void main(String[] args) {
    		Person p1 = new Person("tom", 18);
    		Person p2 = new Person("jack", 19);
    		Map map = new HashMap<>();
    		map.put(p1, "111");
    		map.put(p2, "2222");
    		// key的字段发生了改变
    		p1.setAge(5);
    		System.out.println(map.get(p1));
    		System.out.println(map.get(p2));
    	}
    }
    

      

       所以使用hashmap不能轻易地去修改key的字段值,但此时map中还是存在有三个元素,只不过用get(p1)此时只能获取到被修改了过后的key对应的value值:但是可以看的出来p1引用都指向的是同一个对象

    public static void main(String[] args) {
    		Person p1 = new Person("tom", 18);
    		Person p2 = new Person("jack", 19);
    		Map map = new HashMap<>();
    		map.put(p1, "111");
    		map.put(p2, "2222");
    		// key的字段发生了改变
    		p1.setAge(5);
    		map.put(p1, "333");
    		System.out.println(map);
    		System.out.println(map.size());
    		System.out.println(map.get(p1));
    		System.out.println(map.get(p2));
    }
    

      

  • 相关阅读:
    微信小程序 request请求封装
    JavaScript中使用比较多的两种创建对象的方式
    angularjs中audio/video 路径赋值问题
    ajax渲染swiper问题
    angularjs与vue循环数组对象是区别
    gulp安装搭建前端项目自动化
    vue中-webkit-box-orient:vertical打包放到线上不显示
    Redis高级客户端Lettuce详解
    redis单点、redis主从、redis哨兵 sentinel,redis集群cluster配置搭建与使用
    Java线程、线程池ThreadPoolExecutor详细剖析
  • 原文地址:https://www.cnblogs.com/dashenaichicha/p/12602413.html
Copyright © 2011-2022 走看看