Effective Java Methods Common to All Objects

Obey the general contract when overriding equals

 

先了解equals 和 == 的区别,如果不重写equals, equals比较的仅仅只是是否引用同一个对象,==更多的是比较基本数值。当我们创建一些对象的时候。

当对象是单例模式不需要进行 equals 重写。

Reflexive: For any non-null reference values x,x.equals(x) must return true.

Symmetric:For any non-null reference values x and y,x.equals(y) must return true if and only if y.equals(x) returns true

Transitive:For any non-null reference values x,y,z,if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) must return true.

Consistent: For any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.

For any non-null reference value x,x.equals(null) must return false.

 

以及,要明白hashcode的作用,与equals的关系。

package all;

import java.util.Collection;
import java.util.HashSet;

public class Test5 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
       Collection c = new HashSet ();
       Address s1 = new Address("05");
       Address s2 = new Address("05");
       c.add(s1);
       c.add(s2);
     //HashSet()有这个机制,当add的对象发现它hashcode和自己里面已经有的已经相等,自己就会进行相等的对象equals判断,判断为
       //相等,set不会储存相同的值,所以就当只存了一个对象。hashcode是用于散列数据的快速存取,如利用HashSet/HashMap/Hashtable类来存储数据时,都是根据存储对象的hashcode值来进行判断是否相同的。
       //详情  http://www.importnew.com/8701.html   关键点 一些collection的比较先从hashcode开始,所以才能快速。
       System.out.println("----------------");
       System.out.println(s1.equals(s2));
       System.out.println(s1.hashCode());
       System.out.println(s2.hashCode());
       System.out.println(c);
        
    }
}

class Address{
    private String addressName;
    public Address(String addressName){
        this.addressName=addressName;
    }
    
    public String toString(){
        return this.addressName;
    }
    
    @Override
    public boolean equals (Object o){
        if (this==o){//对象自身相等原则
            return true;
        }
        if (o==null){//空值返回false 原则
            return false;
        }
        if (o.getClass()!=getClass()){// 类型相同原则
            return false;
        }
        
        Address addr = (Address) o;//之后是实例化进行逻辑比较
        if (!addr.addressName.equals(this.addressName)){
            return false;
        }
        
        System.out.println("Use equals!");
        return true;
    }
    
    @Override
    public int hashCode(){//hashcode值 很重要,尤其是涉及collection。
        return this.addressName.hashCode();
    }
}
/*
输出以下:  
Use equals!
----------------
Use equals!
true
1541
1541
[05]
会发现在分割线之上凭空多一个 use equals? 这是因为在 hashset 添加的时候,会先进行hashcode 进行比较,一样hashcode值得对象调用equals
比较得出完全一样的对象,根据hashset不重复的特性,最后只有一个值  05 ,如果试着把hashcode 方法去掉 ,则在第一步hashcode值判断就会不一样,
不会进行下一步的  equals 判断,则会输出两个 05,而实际我们希望他们是同一个对象。
  
  */


 

但是如果集合中已经存在一万条数据或者更多的数据,如果采用equals方法去逐一比较,效率必然是一个问题。此时hashCode方法的作用就体现出来了,当集合要添加新的对象时,先调用这个对象的hashCode方法,得到对应的hashcode值,实际上在HashMap的具体实现中会用一个table保存已经存进去的对象的hashcode值,如果table中没有该hashcode值,它就可以直接存进去,不用再进行任何比较了;如果存在该hashcode值, 就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址,所以这里存在一个冲突解决的问题,这样一来实际调用equals方法的次数就大大降低了,说通俗一点:Java中的hashCode方法就是根据一定的规则将与对象相关的信息(比如对象的存储地址,对象的字段等)映射成一个数值,这个数值称作为散列值。

也就是说对于两个对象,如果调用equals方法得到的结果为true,则两个对象的hashcode值必定相等;

  如果equals方法得到的结果为false,则两个对象的hashcode值不一定不同;

  如果两个对象的hashcode值不等,则equals方法得到的结果必定为false;

  如果两个对象的hashcode值相等,则equals方法得到的结果未知。

 

Cosider implementing Comparable

Comparable 接口的重写有利于 排序,在遇见一些Collection 的时候 。 除了Comparable 还有Comparator ,前者是比较接口 在类中实现,一个是比较器,创建一个类来实现,代码如下。

public class Cat implements Comparable<Cat> {
       private int age;
       private String name;
    public Cat(int age,String name){
        this.name=name;
        this.age=age;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
    @Override
    public int compareTo(Cat o) {//重写比较接口
        // TODO Auto-generated method stub
        
        return (this.age-o.age);
    }
       
}


public class MyComparator implements Comparator<Cat>{//比较器的扩展

    @Override
    public int compare(Cat arg0, Cat arg1) {
        // TODO Auto-generated method stub
        return (arg1.getAge()-arg0.getAge());
    }

}




public class Test2 {

    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        ArrayList<Cat> list = new  ArrayList<Cat>();
        list.add(new Cat(1,"1"));
        list.add(new Cat(5,"5"));
        list.add(new Cat(2,"2"));
        list.add(new Cat(4,"4"));
        list.add(new Cat(3,"3"));
        Collections.sort(list);
        for (Cat a:list){
            System.out.println(a.getAge());
        }
        Collections.sort(list, new MyComparator());
        for (Cat a:list){
            System.out.println(a.getAge());
        }
        
    }

}


/*
输出
1
2
3
4
5
5
4
3
2
1
*/

 

转载于:https://www.cnblogs.com/s1127736971/p/7447458.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值