=======================原理速记===================================

equals重载后比较内容,==比较指针。否则equls等同于== (Java里源码如此)

所有的“==”都是基于指针级的,也就是说只有它们指向的是同一个对象才被认为是相等.
而对于对象值的相等判断则需要重写并使用.equal()方法
在多数常用类,譬如String中,.equal()已经被默认重写为是值相等的了

两个对象用==号比较,比较的就是 两个对象的引用。
而equals方法比较的是内容。比较String就覆盖了equals方法(自己重定义逻辑相等)

因为内容相等,所以始终输出equals的效果,而==却不一定,例子:
http://www.cnblogs.com/zhxhdean/archive/2011/03/25/1995431.html

================================equals哲学============================

1. 何时需要重写equals()
当一个类有自己特有的“逻辑相等”概念(不同于对象身份的概念)。

2. 设计equals()
[1]使用instanceof操作符检查“实参是否为正确的类型”。
[2]对于类中的每一个“关键域”,检查实参中的域与当前对象中对应的域值。
[2.1]对于非float和double类型的原语类型域,使用==比较;
[2.2]对于对象引用域,递归调用equals方法;
[2.3]对于float域,使用Float.floatToIntBits(afloat)转换为int,再使用==比较;
[2.4]对于double域,使用Double.doubleToLongBits(adouble) 转换为int,再使用==比较;
[2.5]对于数组域,调用Arrays.equals方法。

3. 当改写equals()的时候,总是要改写hashCode()
根据一个类的equals方法(改写后),两个截然不同的实例有可能在逻辑上是相等的,但是,根据Object.hashCode方法,它们仅仅是两个对象。因此,违反了“相等的对象必须具有相等的散列码”。

4. hashCode最大的用处是什么呢?

Java中的集合(Collection)有两类,一类是List,再有一类是Set。 前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。
那么这里就有一个比较严重的问题了:要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢? 这就是Object.equals方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。Java采用了哈希表的原理, 哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上. 初学者可以这样理解,hashCode方法实际上返回的就是对象存储的物理地址(实际可能并不是)。 有了hashCode,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。 如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了, 就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。 所以这里存在一个冲突解决的问题。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。

5. 为什么在Hibernate里要重写hashCode和equals这两个方法?
在hibernate中,经常使用set集合来保存相关对象,而set集合是不允许重复的, so, 道理同上。

===========================一道写HashCode的题===========================

一道java hashCode()的面试题
最近面试老是被问到这个问题。。。

public class ValuePair {
public int a = 4, b; public boolean equals(Object other) {
try {
ValuePair o = (ValuePair) other;
return ((a == o.a) && (b == o.b)) || ((a == o.b) && (b == o.a));
} catch (ClassCastException cce) {
return false;
}
} public int hashCode() {
// 请选择下边的答案(多选)
}
}

A。return 0;
B. return a;
C. return a+b;
D. return a-b;
E. return a^b;
F. return (a<<16)|b;
请说明理由。

------------------------------------第一种解答----------------------------------------------------------------------
hashCode 的常规协定是:
在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。
如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。
如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不 要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。
实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。)

然后再看重写的equals方法。。
(a==o.a;;b==o.b) || (a==o.b;;b==o.a); 说明交换a,b的值不会对结果产生影响,也要生成相同的hashcode值。

所以选ACE。。。(Cliff评注:A还是不能选)

------------------------------------第二种解答----------------------------------------------------------------------

根据一般约定:
如果2个对象 equals 比较为true,那么hashCode也最好(不是必须)相同。(Cliff:我也比较同意,这是最好,但不是必须)
如果2个对象 equals 比如为false,那么hashCode也最好(不是必须)不同。

因此对于这个题目,如果从纯语法层面考虑,全部都是可选的
但是从程序运行效率来看,最好是该hashCode里,a,b值可以互换,而又尽可能做到不同的a,b值返回不同的值。因为C,E最好.

A. return 0; 效率太低
B. return a; 不满足a,b的互换性
D. return a-b; 不满足a,b的互换性
F. return (a<<16)|b; 不满足a,b的互换性

另外,比如 a * b 也满足互换性,但是效率稍低,毕竟没加法和位运算快

* Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
* If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
* It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.

===========================另一个例子,用来熟悉语法===========================

package dd;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set; public class SetTest { public static void main(String[] args) {
// Set<String> set = new HashSet<String>();
// set.add("abc"); //将对象的地址增加到集合中了
// set.add("xyz");
// set.add("abc");
//
// for(Iterator<String> iter = set.iterator(); iter.hasNext();) {
// System.out.println(iter.next());
// } Set<People> set = new HashSet<People>();
set.add(new People("zhangfei"));
set.add(new People("guanyu"));
for (Iterator<People> iter = set.iterator(); iter.hasNext();) {
System.out.println(iter.next().getName());
}
// Object object = new Object();
// System.out.println(Integer.toHexString(object.hashCode()));
}
} class People {
private String name; public People(String name) {
this.name = name;
} public String getName() {
return name;
} public boolean equals(Object object) {
if (this == object) { // 第一步
return true;
}
if (object instanceof People) { // 第二步
People people = (People) object;
if (name.equals(people.getName())) { // 第三步,这里很巧妙的使用了String的比较,属于递归调用
return true;
}
}
return false;
} public int hashCode() {
return name.hashCode();
}
}

三、小结
1,如果要用自己的类作为HashMap的key,必须同时覆盖hashCode和equals方法。
2,重写hashCode方法的关键:
(1)对同一个对象调用hashCode()都应该生成同样的值。
(2)hashCode()方法不要依赖于对象中易变的数据,当数据发生变化时,hashCode()就会生成一个不同的散列码,即产生了一个不同的label。
(3)hashCode()不应依赖于具有唯一性的对象信息,例如对象地址。
(4)散列码应该更关心速度,而不是唯一性,因为散列码不必是唯一的。
(5)好的hashCode()应该产生分步均匀的散列码。
参考:
http://blog.csdn.net/lazy_tiger/article/details/1816946

Java的==与equals之辨的更多相关文章

  1. Java的==与equals之辨,简单解释,很清楚

    "=="和equals方法究竟有什么区别? (单独把一个东西说清楚,然后再说清楚另一个,这样,它们的区别自然就出来了,混在一起说,则很难说清楚) ==操作符专门用来比较两个变量的值 ...

  2. 浅谈Java中的equals和==(转)

    浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str ...

  3. 浅谈Java中的equals和==

    浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: String str1 = new String("hello"); String str2 = ...

  4. Java hashCode() 和 equals()的若干问题

    原文:http://www.cnblogs.com/skywang12345/p/3324958.html 本章的内容主要解决下面几个问题: 1 equals() 的作用是什么? 2 equals() ...

  5. Java中的equals和hashCode方法

    本文转载自:Java中的equals和hashCode方法详解 Java中的equals方法和hashCode方法是Object中的,所以每个对象都是有这两个方法的,有时候我们需要实现特定需求,可能要 ...

  6. Java提高篇——equals()与hashCode()方法详解

    java.lang.Object类中有两个非常重要的方法: 1 2 public boolean equals(Object obj) public int hashCode() Object类是类继 ...

  7. Java hashCode() 和 equals()的若干问题解答

    本章的内容主要解决下面几个问题: 1 equals() 的作用是什么? 2 equals() 与 == 的区别是什么? 3 hashCode() 的作用是什么? 4 hashCode() 和 equa ...

  8. Java中==、equals、hashcode的区别与重写equals以及hashcode方法实例(转)

    Java中==.equals.hashcode的区别与重写equals以及hashcode方法实例  原文地址:http://www.cnblogs.com/luankun0214/p/4421770 ...

  9. java String的equals,intern方法(转载)

    JAVA中的equals和==的区别 ==比较的是2个对象的地址,而equals比较的是2个对象的内容. 显然,当equals为true时,==不一定为true: 基础知识的重要性,希望引起大家的重视 ...

随机推荐

  1. VirtualBox实现宿主机和虚拟机之间网络的通讯

    摘要:实现宿主机和虚拟机之间网络的通讯 环境: 宿主机操作系统            WindowsXP 虚拟机软件                    VirtualBox 虚拟机操作系统     ...

  2. iOS开发-项目的完整重命名方法,图文教程。

    前言:在IOS开发中,有时候想改一下项目的名字,都会遇到很多麻烦.直接改项目名吧,XCODE又不会帮你改所有的名字.总是有很多文件.文件夹或者是项目设置的项.而且都是不能随便改的,有时候改着改着,编译 ...

  3. C# mvc统一通道使用过滤器

    问题描述 使用C#过滤器有一个最大的问题就是在过滤器转向后程序仍然会执行方法体 问题解决思路 使用统一通道执行方法 不直接进入控制器 通过反射调用 using System; using System ...

  4. 数据库面试题.net

    1.ADO.net中常用的对象 connection, command, sqladapter, dataset, dataview. 2.net中读写数据库要用到哪些类 DataSet数据存储 Da ...

  5. C语言学习笔记(二) 基础知识

    数据类型 C语言数据可以分为两大类: 基本类型数据和复合类型数据: 基本类型数据 整数 整型   (int)  ——占4字节 短整型(short int)  ——占2字节    长整型(long in ...

  6. Telerik UI for ASP.NET Core概要

    介绍:不介绍了,刚开始研究. 下载:CSDN或者51cto上都有最新的开发版 安装:默认的安装目录是C:\Program Files (x86)\Progress\Telerik UI for ASP ...

  7. Atitit.atiDataStoreService   v2 新特性

    Atitit.atiDataStoreService   v2 新特性 1.1. V1  基础实现1 1.2. V2  增加了对  $uuid  $cur_uid参数的支持1 1.3. 增加了fld  ...

  8. hdu 4597 Play Game(记忆化搜索)

    题目链接:hdu 4597 Play Game 题目大意:给出两堆牌,仅仅能从最上和最下取,然后两个人轮流取,都依照自己最优的策略.问说第一个人对多的分值. 解题思路:记忆化搜索,状态出来就很水,dp ...

  9. IDEA13中配置struts错误:ClassNotFoundException: org...dispatcher.ng.filter.StrutsPrepareAndExecuteFilter +找不到java程序包 解决办法

    问题一:ClassNotFoundException: org...dispatcher.ng.filter.StrutsPrepareAndExecuteFilter解决办法 1.确保所有strut ...

  10. python剑指网络篇二

    在socket编程中 AF_INET 对应 IPv4 SOCK_STREAM 对应 TCP SOCK_DGRAM 对应 UDP