Java中Set的contains()方法——hashCode与equals方法的约定及重写原则
新手对Set中contains()方法的疑惑
- import java.util.HashSet;
- class Dog{
- String color;
- public Dog(String s){
- color = s;
- }
- }
- public class SetAndHashCode {
- public static void main(String[] args) {
- HashSet dogSet = new HashSet();
- dogSet.add(new Dog("white"));
- dogSet.add(new Dog("white"));
- System.out.println("We have " + dogSet.size() + " white dogs!");
- if(dogSet.contains(new Dog("white"))){
- System.out.println("We have a white dog!");
- }else{
- System.out.println("No white dog!");
- }
- }
- }
上述代码的输出为:
- We have 2 white dogs!
- No white dog!
程序中添加了两只白色的小狗到集合dogSet中. 且 size()方法显示有2只白色的小狗.但为什么用
contains()方法来判断时却提示没有白色的小狗呢?
Set的contains(Object o)
方法详解
Java的API文档指出: 当且仅当 本set包含一个元素 e,并且满足(o==null ? e==null :
o.equals(e))条件时,contains()方法才返回true. 因此 contains()方法
必定使用equals方法来检查是否相等.
需要注意的是: set 中是可以包含 null值的(常见的集合类都可以包含null值).
所以如果添加了null,然后判断是否包含null,将会返回true,代码如下所示:
- HashSet a = new HashSet();
- a.add(null);
- if(a.contains(null)){
- System.out.println("true");
- }
Java的根类Object定义了 public boolean equals(Object
obj) 方法.因此所有的对象,包括数组(array,[]),都实现了此方法。
在自定义类里,如果没有明确地重写(override)此方法,那么就会使用Object类的默认实现.即只有两个对象(引用)指向同一块内存地址(即同一个实际对象,
x==y为true)时,才会返回true。
如果把Dog类修改为如下代码,能实现我们的目标吗?
- class Dog{
- String color;
- public Dog(String s){
- color = s;
- }
- //重写equals方法, 最佳实践就是如下这种判断顺序:
- public boolean equals(Object obj) {
- if (!(obj instanceof Dog))
- return false;
- if (obj == this)
- return true;
- return this.color == ((Dog) obj).color;
- }
- }
英文答案是: no.
问题的关键在于 Java中hashCode与equals方法的紧密联系.
hashCode() 是Object类定义的另一个基础方法.
equals()与hashCode()方法之间的设计实现原则为:
如果两个对象相等(使用equals()方法),那么必须拥有相同的哈希码(使用hashCode()方法).
即使两个对象有相同的哈希值(hash code),他们不一定相等.意思就是: 多个不同的对象,可以返回同一个hash值.
hashCode()的默认实现是为不同的对象返回不同的整数.有一个设计原则是,hashCode对于同一个对象,不管内部怎么改变,应该都返回相同的整数值.
在上面的例子中,因为未定义自己的hashCode()实现,因此默认实现对两个对象返回两个不同的整数,这种情况破坏了约定原则。
解决办法
- class Dog{
- String color;
- public Dog(String s){
- color = s;
- }
- //重写equals方法, 最佳实践就是如下这种判断顺序:
- public boolean equals(Object obj) {
- if (!(obj instanceof Dog))
- return false;
- if (obj == this)
- return true;
- return this.color == ((Dog) obj).color;
- }
- public int hashCode(){
- return color.length();//简单原则
- }
- }
Java中Set的contains()方法——hashCode与equals方法的约定及重写原则的更多相关文章
- Java 中正确使用 hashCode 和 equals 方法
在这篇文章中,我将告诉大家我对hashCode和equals方法的理解.我将讨论他们的默认实现,以及如何正确的重写他们.我也将使用Apache Commons提供的工具包做一个实现. 目录: hash ...
- K:java中的hashCode和equals方法
hashCode和equals方法是Object类的相关方法,而所有的类都是直接或间接的继承于Object类而存在的,为此,所有的类中都存在着hashCode和equals.通过翻看Object类 ...
- (转)Java 中正确使用 hashCode 和 equals 方法
背景:最近在编写持久化对象时候遇到重写equals和hashCode方法的情况,对这两个方法的重写做一个总结. 链接:https://www.oschina.net/question/82993_75 ...
- 关于java中的hashcode和equals方法原理
关于java中的hashcode和equals方法原理 1.介绍 java编程思想和很多资料都会对自定义javabean要求必须重写hashcode和equals方法,但并没有清晰给出为何重写此两个方 ...
- Java中正确使用hashCode和equals方法
在这篇文章中,我将告诉大家我对hashCode和equals方法的理解.我将讨论他们的默认实现,以及如何正确的重写他们.我也将使用Apache Commons提供的工具包做一个实现. 目录: hash ...
- 使用hashCode()和equals()方法 - Java
在这篇文章中,我将指出我对hashCode()和equals()方法的理解.我将讨论它们的默认实现以及如何正确地覆盖它们.我还将使用Apache Commons包中的实用工具类来实现这些方法. has ...
- 为什么要重写hashcode和equals方法?初级程序员在面试中很少能说清楚。
我在面试 Java初级开发的时候,经常会问:你有没有重写过hashcode方法?不少候选人直接说没写过.我就想,或许真的没写过,于是就再通过一个问题确认:你在用HashMap的时候,键(Key)部分, ...
- 重写Java Object对象的hashCode和equals方法实现集合元素按内容判重
Java API提供的集合框架中Set接口下的集合对象默认是不能存储重复对象的,这里的重复判定是按照对象实例句柄的地址来判定的,地址相同则判定为重复,地址不同不管内容如何都判定为不重复,这有时与需求不 ...
- 【Java实战】源码解析为什么覆盖equals方法时总要覆盖hashCode方法
1.背景知识 本文代码基于jdk1.8分析,<Java编程思想>中有如下描述: 另外再看下Object.java对hashCode()方法的说明: /** * Returns a hash ...
随机推荐
- Selenium入门10 弹出框的处理 switch_to.alert
三种弹出框alert(一个按钮),confirm(两个确认,取消),prompt(两个按钮+输入框). 切换到弹框: switch_to_alert() 新版的selenium用: brows ...
- C++学习之继承中的成员访问控制
由基类到派生类的过程中,在派生类里如何访问基类成员,以及派生类对象如何访问基类成员,是根据派生类在从基类派生时是以什么方式进行的派生:public.protect或者private.下面说一下在这三种 ...
- 整合ssm集成框架
第一步:配置pom.xml 该代码放在<dependencies>里面 <!--spring 所需要的jar包 web.aop.jdbc.webmvc--> <!--1. ...
- 前端jQuery之属性操作
属性操作主要分为四个部分:html属性操作,dom属性操作,类样式操作和值操作 HTML属性操作:属性的读取,设置,以及移除,如attr().removeAttr() DOM属性操作:属性的读取,设置 ...
- UITabBarController的tabBarItem图标真机不显示
在xib中分别设置了图标选择和未选择的图片 模拟器效果 选中 未选中 当时使用多种机型进行测试时发现部分机型第一次进入应用除第一个tabbaritem图标可以显示,其余均不能显示,点击其余tabbar ...
- 1、React-Native的基础入门
React Native (简称RN)是Facebook于2015年4月开源的跨平台移动应用开发框架,是Facebook早先开源的JS框架 React 在原生移动应用平台的衍生产物,目前支持iOS和安 ...
- 批量更新python库
import pip from subprocess import call for dist in pip.get_installed_distributions(): try: call(&quo ...
- 彻底弄懂session,cookie,token
session,cookie和token究竟是什么 简述 我在写之前看了很多篇session,cookie的文章,有的人说先有了cookie,后有了session.也有人说先有session,后有co ...
- php-5.6.26源代码 - PHP文件汇编成opcode(require、include的差异)
文件 php-5.6.26/Zend/zend_language_scanner.c ZEND_API zend_op_array *compile_file(zend_file_handle *fi ...
- vim编辑器使用习惯问题
Ubuntu中vi在编辑状态下方向键不能用,一按方向键盘就出ABCD,想插入个字母还非常麻烦,还有回格键不能删除等我们平时习惯的一些键都不能使用. 解决办法: 可以安装vim full版本,在full ...