equals()和hashcode()分析

A.==
1、基本类型,比较内容。

2、引用类型,比较地址。


B.equals
1.首先equals()和hashcode()这两个方法都是从object类中继承过来的。 equals()方法在object类中定义如下(默认比较地址): 

<span style="white-space:pre">	</span>public boolean equals(Object obj) { 
<span style="white-space:pre">		</span>return (this == obj); 
<span style="white-space:pre">	</span>}
2.String中,jdk重写了equals方法,此时可以看出,比较的是内容

<span style="white-space:pre">	</span>public boolean equals(Object anObject) {
<span style="white-space:pre">		</span>if (anObject instanceof String) {
<span style="white-space:pre">			</span>String anotherString = (String) anObject;
<span style="white-space:pre">			</span>int n = count;
<span style="white-space:pre">			</span>if (n == anotherString.count) {
<span style="white-space:pre">				</span>char v1[] = value;
<span style="white-space:pre">				</span>char v2[] = anotherString.value;
<span style="white-space:pre">				</span>int i = offset;
<span style="white-space:pre">				</span>int j = anotherString.offset;
<span style="white-space:pre">				</span>while (n-- != 0) {
<span style="white-space:pre">					</span>if (v1[i++] != v2[j++])
<span style="white-space:pre">						</span>return false;
<span style="white-space:pre">				</span>}
			return true;
		    }
		}
<span style="white-space:pre">		</span>return false;
<span style="white-space:pre">	</span>}


C.hashcode()
1. hashcode()方法,在object类中定义如下: 
  public native int hashCode(); 
说明是一个本地方法,它的实现是根据本地机器相关的。

2.String类中重写了hashcode()方法如下:
<span style="white-space:pre">	</span>public int hashCode() { 
<span style="white-space:pre">		</span>int h = hash; 
<span style="white-space:pre">		</span>if (h == 0) { 
<span style="white-space:pre">			</span>int off = offset; 
    			char val[] = value; 
    			int len = count; 
           		for (int i = 0; i < len; i++) { 
                	h = 31*h + val[off++]; 
            	} 
            	hash = h; 
       	 	} 
       		 return h; 
<span style="white-space:pre">	</span>}


D.这里我们首先要明白一个问题:
1.equals()相等的两个对象,hashcode()一定相等; 
2.equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。换句话说,equals()方法不相等的两个对象,hashcode()有可能相等。(我的理解是由于哈希码在生成的时候产生冲突造成的)。 

E.谈到hashcode()和equals()就不能不说到 hashset,hashmap,hashtable中的使用,具体是怎样呢,请看如下分析: 
1.Hashset是继承Set接口,Set接口又实现Collection接口,这是层次关系。那么hashset是根据什么原理来存取对象的呢? 
 在hashset中不允许出现重复对象,元素的位置也是不确定的。在hashset中又是怎样判定元素是否重复的呢?
 判断两个对象是否相等的规则是: 
1),判断两个对象的hashCode是否相等: 如果不相等,认为两个对象也不相等,完毕 ,如果相等,转入2) 
(这一点只是为了提高存储效率而要求的,其实理论上没有也可以,但如果没有,实际使用时效率会大大降低,所以我们这里将其做为必需的。后面会重点讲到这 个问题。) 
2),判断两个对象用equals运算是否相等:如果不相等,认为两个对象也不相等, 如果相等,认为两个对象相等(equals()是判断两个对象是否相等的关键) 

2.看看Hashset
<span style="white-space:pre">	</span>@Test
	public void test2() {
		String s1 = new String("zhaoxudong");
		String s2 = new String("zhaoxudong");
		System.out.println(s1 == s2);// false
		System.out.println(s1.equals(s2));// true
		System.out.println(s1.hashCode());// s1.hashcode()等于s2.hashcode()
		System.out.println(s2.hashCode());

		/**
		 * 此时add后,如果s1和s2是同一个对象,则会覆盖,hashset只有一个元素。
		 */
		Set hashset = new HashSet();
		hashset.add(s1);
		hashset.add(s2);
		
		/**
		 * 结果:hashset只有一个元素。
		 * 原因:实质上在添加s1,s2时,运用上面说到的两点准则(因为String类已经重写了equals()方法和hashcode()方法,
		 * 	所以在根据上面的第1.2条原则判定时,s1和s2在HashSet中被认为是同一个对象),可以知道hashset认为s1和s2是相等的,是在添加重复<span style="white-space:pre">	</span>元<span style="white-space:pre">			</span>素,所以让s2覆盖了s1;
		 */
		Iterator it = hashset.iterator();
		while (it.hasNext()) {
			System.out.println(it.next());
		}
	}
3.HashSet添加我们自己写的对象,没有重写equals和hashcode,没有实现 HashSet去重复功能

public class JtestHashCode {
<span style="white-space:pre">	</span>public static void main(String[] args) {
<span style="white-space:pre">		</span>HashSet hs = new HashSet();
<span style="white-space:pre">		</span>hs.add(new Student(1, "zhangsan"));
<span style="white-space:pre">		</span>hs.add(new Student(2, "lisi"));
<span style="white-space:pre">		</span>hs.add(new Student(3, "wangwu"));
<span style="white-space:pre">		</span>hs.add(new Student(1, "zhangsan"));

<span style="white-space:pre">		/**
<span style="white-space:pre">		</span> * 得出来的结果,存在重复的new Student(1, "zhangsan"),
<span style="white-space:pre">		</span> * 原因:由于我们没重写Student类的equals和hashcode,导致两个new Student(1, "zhangsan")不是同一对象,这就没有实现HashSet的去重复,
			其实本来就不是同一个,但是要实现HashSet的去重复功能,必须就得重写Student类的equals和hashcode
<span style="white-space:pre">		</span> */</span>
<span style="white-space:pre">		</span>Iterator it = hs.iterator();
<span style="white-space:pre">		</span>while (it.hasNext()) {
<span style="white-space:pre">			</span>System.out.println(it.next());
<span style="white-space:pre">		</span>}
<span style="white-space:pre">	</span>}
}


class Student {
<span style="white-space:pre">	</span>int num;
<span style="white-space:pre">	</span>String name;


<span style="white-space:pre">	</span>Student(int num, String name) {
<span style="white-space:pre">		</span>this.num = num;
<span style="white-space:pre">		</span>this.name = name;
<span style="white-space:pre">	</span>}


<span style="white-space:pre">	</span>public String toString() {
<span style="white-space:pre">		</span>return num + ":" + name;
<span style="white-space:pre">	</span>}
}

4 .HashSet添加我们自己写的对象,实现 HashSet去重复功能

public class JtestHashCode {
	public static void main(String[] args) {
		HashSet hs = new HashSet();
		hs.add(new Student(1, "zhangsan"));
		hs.add(new Student(2, "lisi"));
		hs.add(new Student(3, "wangwu"));
		hs.add(new Student(1, "zhangsan"));

		/**
		 * 得出来的结果,HashSet去掉重复了,
		 * 原因:我们没重写Student类的equals和hashcode,在HashSet添加对象的时候,jdk会比较对象是否存在
		 */
		Iterator it = hs.iterator();
		while (it.hasNext()) {
			System.out.println(it.next());
		}
	}
}

class Student {
	int num;
	String name;

	Student(int num, String name) {
		this.num = num;
		this.name = name;
	}

	public int hashCode() {
		return num * name.hashCode();
	}

	public boolean equals(Object o) {
		Student s = (Student) o;
		return num == s.num && name.equals(s.name);
	}

	public String toString() {
		return num + ":" + name;
	}
}

F.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值