接下来我们要讨论如下问题:
1、Set接口的 contains 方法,判断是否包含的依据是什么?
2、对象 hashCode equals 方法之间的关系

1、Set接口的 contains 方法,判断是否包含的依据是什么?

我查看了一下接口文档,里面是这样描述的:
该方法重写了 Collection 接口的 contains 方法

Returns true if this set contains the specified element. More formally, returns true if and only if this set contains an element e such that (o == null ? e==null : o.equals(e)).

也就是说,当且仅当
1:参数o,如果o为空,set中也有空时
2:参数o.equals(e),e为set中的一个元素
上述两种情况,会返回true。

2、对象 hashCode equals 方法之间的关系

同样,阅读接口文档, equals 方法说明如下:

Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes

就是说,如果一个对象重写了 equals 方法,通常也需要重写 hashCode 方法。根据契约约定,如果两个对象相等,则它们的hash值必须相等。
换句话说,如果两个对象的hash值不同,则调用它们的 .equals 去比较,肯定返回 false

阅读 hashCode 的文档说明:

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.

如果两个对象相等,则必须返回相等的hash值。这和 equals 说明一致。

It is not required that if two objects are unequal according to the equals(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 hash tables.

简单的说,如果两个对象不相等,它们的hash值可能相等。
所以,不能认为hash值一样,就说两个对象相等。

As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language.)

通常,不同对象还是需要返回不同的hash值。通常是通过将对象的内部地址转换为integer实现的。

我自定义一个Dog对象,先不重写 equals hashCode ,当Set中添加了两个白色的狗对象时,我们用 contains 方法去校验Set中是否包含白色的狗对象,会得到如下结果:

import java.util.HashSet;
import java.util.Set;
 * created at 2018-10-08 17:24
 * @author lerry
class Dog {
	String color;
	public Dog(String s) {
		color = s;
public class SetAndHashCode {
	public static void main(String[] args) {
		Set<Dog> dogSet = new HashSet<>();
		dogSet.add(new Dog("white"));
		dogSet.add(new Dog("white"));
		System.out.printf("we have %d white dogs", dogSet.size());
		System.out.println();
		if (dogSet.contains(new Dog("white"))) {
			System.out.println("Set has white dog!");
		else {
			System.out.println("Set don't have white dog!");
console results:
we have 2 white dogs
Set don't have white dog!

这说明:
默认new一个新对象,会产生新的hash值。

可以验证一下:

public class SetAndHashCode {
	public static void main(String[] args) {
		System.out.println(new Dog("white").hashCode());
		System.out.println(new Dog("white").hashCode());
console results:
2000502626
704603837

接下来,我们重新Dog类的equals方法,让类认为只要颜色一样,就算相等:

class Dog {
	String color;
	public Dog(String s) {
		color = s;
	public String getColor() {
		return color;
	@Override
	public boolean equals(Object obj) {
		if (obj instanceof Dog && this.color.equals(((Dog) obj).getColor())) {
			return true;
		else {
			return false;
public class SetAndHashCode {
	public static void main(String[] args) {
		Set<Dog> dogSet = new HashSet<>();
		dogSet.add(new Dog("white"));
		dogSet.add(new Dog("white"));
		System.out.printf("we have %d white dogs", dogSet.size());
		System.out.println();
		if (dogSet.contains(new Dog("white"))) {
			System.out.println("Set has white dog!");
		else {
			System.out.println("Set don't have white dog!");
console results:
we have 2 white dogs
Set don't have white dog!

但是结果并没有什么改变。对了,根据如果两个对象相等,则它们的hash值必须相等原则,我们还应该去重写hashCode方法:

@Override
	public int hashCode() {
		return this.color.hashCode();

这时,控制台返回的结果终于变成了:

we have 1 white dogs
Set has white dog!

Set对重复元素,进行了去重。所以,添加了两次

		dogSet.add(new Dog("white"));
		dogSet.add(new Dog("white"));

后,dogSet.size()依旧为1

Java中hashCode与equals方法的约定及重写原则
jdk api

代码环境描述

jdk 1.7
macOS 10.13.4

概述接下来我们要讨论如下问题:1、Set接口的contains方法,判断是否包含的依据是什么?2、对象hashCode和equals方法之间的关系1、Set接口的contains方法,判断是否包含的依据是什么?我查看了一下接口文档,里面是这样描述的:该方法重写了Collection接口的contains方法Returns true if this set contains the ...    Set集合的元素不区分顺序,且不允许出现相同元素。这里同样的元素指的是以equals()方法判断的 2、列表List    List列表中的记录元素添加的顺序,而且可以填充相同的元素。 3、映射Map    映射中包含的都 翻译时间: 2013年11月5日 原文链接: Java hashCode() and equals() Contract for the contains(Object o) Method of Set 本文主要讨论 集合Set 中存储对象的 hash...
Java编程离不开容器,使用容器又会常常用到contains()方法,这篇文章通过极其详细的测试,探究了 javacontains() 方法实现的底层原理。 索引第一波测试 第一波测试 String 和自定义 object 类之间储存方式的区别 String 和 object在使用 contains 时的差别 List Set Map 的不同表现 //注释为false的是错误,没写的是t...
Set接口的实现类 HashSet与LinkedHashSet HashSet与LinkedHashSet关系就如同HashMap和LinkedHashMap一样。HashSet内部保存了一个HashMap对象来存储。 利用Map对象,存入Map的k-v中value对象始终是同一个对象(就是上图中声明的private static f...
JavaSetcontains()方法 —— hashCodeequals方法 最近写项目的时候遇到了这个问题,就是我在一个ArrayList里放了一个很多个vo,每当我要在里面添加vo的时候,我都要判断一下,这个list里是否已经存在,若是存在,则不添加。虽然知道是用contains()方法,但用了之后发现一直都是false,就是无论怎么判断都是会插进去。 然后,创建一个Node的Set集合,并add一个Node对象nd1,同时new一个xy值与nd1相同的nd2: Node nd1 = new Node(1,2); Node nd2 = new Node(1,2); Set<Node> st=new HashSet<>
   1、默认情况(没有覆盖equals方法)下equals方法都是调用Object类的equals方法,而Objectequals方法主要用于判断对象的内存地址引用是不是同一个地址(是不是同一个对象)。 2 、要是类中覆盖了equals方法,那么就要根据具体的代码来确定equals方法的作用了,覆盖后一般都是通过对象的内容是否相等来判断对象是否相 Map mapItem = new HashMap(); Object tempObj = someObj; if(!StringUtils.isEmpty(tempObj.toString())){ //先转成json字符,再转回json对象,JSON实际上是实现Map接口的子类,所以可以直接赋值给Map对象 mapItem = JSON.parseObject(JSON.toJSONString(tempObj)); mapItem.pu public class SetTest { public static void main(String[] args) { Set set = new HashSet(); set.add("aaa"); set.add("