==、hashCode()、equals(Object obj)方法

来源:互联网 发布:csgo a卡优化 编辑:程序博客网 时间:2024/06/05 16:33

1、”==”运算符是用来比较两个变量的值是否相等。也就是说,该运算比较的是变量对应的内存中所存储的数值是否相等,要比较两个基本类型的数据或两个引用变量是否相等,只能用”==”。具体而言,如果两个变量是基本数据类型,可以直接使用”==”运算符来比较其对应的值是否相等。如果两个变量是引用类型,那么使用”==”则比较的是引用变量所存储的数值(这个数值就是变量指向对象所占用内存的首地址)。

2、equalsObject类提供的方法之一。每一个Java类都继承自Object类,所以每一个对象都具有equals方法。Object类中定的equals(Object)方法是直接使用”==”运算符来比较两个对象,所以在没有覆盖equals(Object)方法的情况下,equals(Object)”==”运算符一样,比较的是引用。

3、hashCode()方法是从Object类中继承过来的,它也用来鉴定两个对象是否相等。Object类中的hashCode()方法返回对象在内存中地址转换成一个int值,所以如果没有重写hashCode()方法,任何对象的hashCode()方法都不相等的。使用上,例如在hashmap中,由于key是不可以重复的,它在判断key是否重复时就用到了hashCode()这个方法,而且也用到了equals()方法。此处“不可以重复”指的是equals()和hashCode()只要有一个值不等就可以了。

实例:

<span style="font-size:18px;">package equals;public class Person {private static int index=1;private String name;private int age;public Person(String name,int age){this.name = name;this.age = age;}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;}}</span>
<span style="font-size:18px;">package equals;import java.util.HashSet;import java.util.LinkedList;import java.util.List;import java.util.Set;public class Test {public static void main(String[] args) {// TODO Auto-generated method stubList<Person> list = new LinkedList<Person>();         Set<Person> set = new HashSet<Person>();                  Person p1  = new Person("张三",12);          Person p2  = new Person("张三",12);           System.out.println("p1 == p1 : "+(p1 == p2));          System.out.println("p1.equals(p1) : "+p1.equals(p2));                  list.add(p1);          list.add(p2);          System.out.println("list size:"+ list.size());                    set.add(p1);          set.add(p2);          System.out.println("set size:"+ set.size());                    }}</span>

1、子类未重写Object类的的equals()hashCode()方法

运行结果:

p1 == p1 : falsep1.equals(p1) : falselist size:2set size:2

结果分析:

Person类没有覆盖equals方法,p1调用equals方法实际上调用的是Objectequals方法。所以采用对象内存地址是否相等来判断对象是否相等。因为是两个新对象所以对象的内存地址不相等,所以p1.equals(p2) false

2、覆盖equals()方法,不覆盖hashCode()方法

@Overridepublic boolean equals(Object obj){if(obj == null){return false;}if(this == obj){return true;}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;}

运行结果:

p1 == p1 : falsep1.equals(p1) : truelist size:2set size:2
结果分析:

因为Person两个对象的agename属性相等,而且又是通过覆盖equals方法来判断的,所示p1.equals(p2true注意以上几次测试listsetsize都是2

3、通过以上的代码运行,我们知道equals方法已经生效。接下来我们覆盖一下hashCode方法(通过agename属性来生成hashcode)并不覆盖equals方法,其中Hash码是通过agename生成的

 @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;    }     

运行结果:

p1 == p1 : falsep1.equals(p1) : falselist size:2set size:2
结果分析:

我们并没有覆盖equals方法只覆盖了hashCode方法,两个对象虽然hashCode一样,但在将p1p2放入set集合时由于equals方法比较的两个对象是false,所以就没有再比较两个对象的hashcode值。


4、我们覆盖一下equals方法和hashCode方法

运行结果:

p1 == p1 : falsep1.equals(p1) : truelist size:2set size:1

结果分析:

结果分析:p1p2通过equals方法比较相等,而且返回的hashCode值一样,所以放入set集合中时只放入了一个对象。

5、下面我们让两个对象equals方法比较相等,但hashCode值不相等试试。
<span style="font-size:18px;">@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;    }     </span>

修改为

<span style="font-size:18px;">@Override    public int hashCode() {          final int prime = 31;          int result = 1;          result = prime * result + age+index++;          result = prime * result + ((name == null) ? 0 : name.hashCode());          return result;    }     </span>
运行结果:

<span style="font-size:18px;">p1 == p1 : falsep1.equals(p1) : truelist size:2set size:2</span>

结果分析:

虽然p1p2通过equals方法比较相等,但两个对象的hashcode的值并不相等,所以在将p1p2放入set集合中时认为是两个不同的对象。

6、修改p1的某个属性值

<span style="font-size:18px;">List<Person> list = new LinkedList<Person>();         Set<Person> set = new HashSet<Person>();                  Person p1  = new Person("张三",12);          Person p2  = new Person("张三",12);           System.out.println("p1 == p1 : "+(p1 == p2));          System.out.println("p1.equals(p1) : "+p1.equals(p2));                  list.add(p1);          list.add(p2);          System.out.println("list size:"+ list.size());                    set.add(p1);          set.add(p2);          System.out.println("set size:"+ set.size());                   p1.setAge(24);          System.out.println("remove p1 : "+set.remove(p1));          System.out.println("set size:"+ set.size());      </span>

运行结果:

<span style="font-size:18px;">p1 == p1 : falsep1.equals(p1) : truelist size:2set size:1remove p1 : falseset size:1</span>

结果分析:

当我们将某个对象存到set中时,如果该对象的属性参与了hashcode的计算,那么以后就不能修改该对象参与hashcode计算的那些属性了,否则会引起意向不到的错误的。正如测试中,不能够移除p1对象


总结:

  1. 覆盖以后,比较对象是否相等将通过覆盖后的equals方法进行比较(判断对象的内容是否相等);
  2. 在没有覆盖equals方法的情况下,两个对象通过equals比较,如果相等,则这两个对象hashcode一定相等,如果equals不等,则hashcode有可能相等,也有可能不等。反过来,如果hashcode不相等,则equals一定不等,如果hashcode相等,equals可能相等也可能不等;
  3. hashcode方法只有在集合中用到;
  4. 将对象放入到集合中时,首先判断要放入对象的hashcode值与集合中的任意一个元素的hashcode值是否相等,如果不相等直接将该对象放入集合中。如果hashcode值相等,然后再通过equals方法判断要放入对象与集合中的任意一个对象是否相等,如果equals判断不相等,直接将该元素放入到集合中,否则不放入。





0 0
原创粉丝点击