Java中Set的contains()方法
本文主要讨论 集合Set 中存储对象的 hashCode 与 equals 方法应遵循的约束关系.新手对Set中contains()方法的疑惑[java]import java.util.HashSet;class Dog{String color;public Dog(String s){color = s;}}public class SetAndHashCode {public static void main(String[] args) {HashSet<Dog> dogSet = new HashSet<Dog>();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!");}}}上述代码的输出为:[plain]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,代码如下所示:[java]HashSet<Dog> a = new HashSet<Dog>();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类修改为如下代码,能实现我们的目标吗?[javaclass 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()实现,因此默认实现对两个对象返回两个不同的整数,这种情况破坏了约定原则。解决办法[java]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();//简单原则}}但是上面的hashCode实现,要求Dog的color是不变的.否则会出现如下的这种困惑:[java]import java.util.HashSet;import java.util.Set;public class TestContains {public static final class Person{private String name = "";public Person(String n) {setName(n);}public String getName() {return name;}public void setName(String name) {this.name = (name==null)? "" : name;}@Overridepublic int hashCode() {// 请考虑是否值得这么做,因为此时name是会变的.return name.length();// 推荐让name不可改变}@Overridepublic boolean equals(Object obj) {if(!(obj instanceof Person)){return false;}if(obj == this){return true;}return this.name.equals(((Person)obj).name);}补充:软件开发 , Java ,
上一个:Java中Set的contains()方法
下一个:二分查找
- 更多JAVA疑问解答:
- java怎么在线读取ftp服务器上的文件内容
- 关于程序员的职业规划
- HTML和JSP矛盾吗?
- java小程序如何打包?
- java怎么split路径文件名?
- jsp+javaBean中Column 'ordersPrice' specified twice的错误
- Java TCP/IP Socket网络编程系列
- 大家来讨论一下我到底该用什么好?Swing 还是 JavaFX
- 关于Hibernate实体自身多对一的抓取问题
- 关于apache2+tomcat群集出现的问题
- spring 获取上下文问题
- SSH 导入导出excel 谁有这块的资料吗?
- Ext TreePanel 刷新问题
- springmvc 加载一个jsp页面执行多个方法 报404
- checkbox数组action怎么向页面传值