equals、==和hashCode

2018-01-13 by Mipha

equals和==

  ==可以用于基本类型和引用类型:当用于基本类型时,比较值是否相同;当用于引用类型时,比较的是所指向的对象的地址是否相同。如果有包装类型,则先将包装类型转换为基本类型再比较值是否相等。当两边都为包装类型时,即为对象,比较的是地址。

  “==”和“!=”比较的是地址,指一个new()出来的地址。

  equals不能作用于基本数据类型的变量,如果没有对equals重写,则比较的的是引用类型的变量所指向的对象的地址。String类的equals方法重写了是比较值。

  下面是String的equals的源码:可以看出String是将字符串拆成字符挨个比较。

public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String) anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false;}

  Integer的equals()方法如下:是Integer的实例且value值也相等的情况下返回true,其他返回false。

public boolean equals(Object obj) { if (obj instanceof Integer) { return value == ((Integer)obj).intValue(); } return false;}

  两个基本型的封装型进行equals()比较,首先equals()会比较类型,如果类型相同,则继续比较值,如果值也相同,返回true。

  基本型和基本封装型进行“==”运算符的比较,基本型封装型会自动拆箱变为基本型后再进行比较。

equals和hashCode

  参考博客

         http://doc.orz520.com/a/doc/2014/0527/2019620.html?from=haosou

         http://www.importnew.com/20381.html

  equals

  默认情况(没有覆盖equals方法)下equals方法都是调用Object类的equals方法,而Object的equals方法主要用于判断对象的内存地址引用是不是同一个地址(是不是同一个对象)。要是类中覆盖了equals方法,那么就要根据具体的代码来确定equals方法的作用了,覆盖后一般都是通过对象的内容是否相等来判断对象是否相等。

  hashCode

  public native int hashCode();

  它是一个本地方法,它的实现与本地机器有关,这里我们暂且认为他返回的是对象存储的物理位置(实际上不是,这里写是便于理解)。

        hashcode方法只有在集合中用到。

  hashCode在扮演的角色为寻域(寻找某个对象在集合中区域位置)。hashCode可以将集合分成若干个区域,每个对象都可以计算出他们的hash码,可以将hash码分组,每个分组对应着某个存储区域,根据一个对象的hash码就可以确定该对象所存储区域,这样就大大减少查询匹配元素的数量,提高了查询效率。

  对于HashMap、HashSet、HashTable而言,它变得异常重要。所以在使用HashMap、HashSet、HashTable时一定要注意hashCode。

  将对象放入到集合中时,首先判断要放入对象的hashcode值与集合中的任意一个元素的hashcode值是否相等,如果不相等直接将该对象放入集合中。如果hashcode值相等,然后再通过equals方法判断要放入对象与集合中的任意一个对象是否相等,如果equals判断不相等,直接将该元素放入到集合中,否则不放入。这样处理,当我们存入大量元素时就可以大大减少调用equals()方法的次数,极大地提高了效率。

Integer类型与int类型的==比较

参考博客:

        http://blog.csdn.net/sgls652709/article/details/49079767

举个例子来说明:

Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;System.out.println(f1 == f2); //trueSystem.out.println(f3 == f4); //false

   同样都是Integer类型的比较,为什么用100比的结果是true,150比的结果是false。

  给一个Integer赋予一个int类型的时候,会调用Integer的静态方法valueOf。

public static Integer valueOf(int i) { assert IntegerCache.high >= 127; if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }

   valueof()是把int 转化成Integer对象类型;(延伸:intValue()是把Integer对象类型变成int的基础数据类型

  在IntegerCache中cache数组初始化如下,存入了-128 - 127的值。

   从上面我们可以知道给Interger 赋予的int数值在-128 - 127的时候,直接从cache中获取,这些cache引用对Integer对象地址是不变的,但是不在这个范围内的数字,则new Integer(i) 这个地址是新的地址,不可能一样的。

  使用Integer a = 1;Integer a = Integer.valueOf(1); 在值介于-128127直接时,作为基本类型。

  使用Integer a = new Integer(1); 时,无论值是多少,都作为对象。

延伸

  java中还有与Integer类似的是Long,它也有一个缓存,在区间[-128,127]范围内获取缓存的值,而Long与long比较的时候先转换成long类型再做值的比较

  Double类型,它没有缓存,但是当Double与double比较的时候会先转换成double类型,再做值的比较

 

最新更新:

第七城市

栏目导航(关闭)