hashcode()和equals()及HashSet判断对象相等。
<wbr style="line-height:25px">1.</wbr>首先equals()和hashcode()这两个方法都是从object类中继承过来的。
publicbooleanequals(Objectobj)
<wbr style="line-height:25px">指示某个其他对象是否与此对象“相等”。<br style="line-height:25px"><span style="line-height:25px"><span style="color:#003366; line-height:25px"><wbr style="line-height:25px">equals方法在非空对象引用上实现相等关系<wbr style="line-height:25px">:</wbr></wbr></span></span><br style="line-height:25px"> *<span style="line-height:25px"><wbr style="line-height:25px">自反性</wbr></span><wbr style="line-height:25px">:对于任何非空引用值x,x.equals(x)都应返回true。<br style="line-height:25px"> *<span style="line-height:25px"><wbr style="line-height:25px">对称性</wbr></span><wbr style="line-height:25px">:对于任何非空引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)才应返回true。<br style="line-height:25px"> *<span style="line-height:25px"><wbr style="line-height:25px">传递性</wbr></span><wbr style="line-height:25px">:对于任何非空引用值x、y和z,如果x.equals(y)返回true,<br style="line-height:25px"> 并且y.equals(z)返回true,那么x.equals(z)应返回true。<br style="line-height:25px"> *<span style="line-height:25px"><wbr style="line-height:25px">一致性:对于任何非空引用值x和y,多次调用x.equals(y)始终返回true或始终返回false,<br style="line-height:25px"> 前</wbr></span><wbr style="line-height:25px">提是对象上equals比较中所用的信息没有被修改。<br style="line-height:25px"> *<span style="line-height:25px"><wbr style="line-height:25px">对于任何非空引用值</wbr></span><wbr style="line-height:25px">x,x.equals(null)都应返回false。<br style="line-height:25px"> 注意:以上这五点是重写equals()方法时,<wbr style="line-height:25px"><span style="color:#0000ff; line-height:25px">必须遵守的准则</span><wbr style="line-height:25px">,如果违反会出现意想不到的结果<br style="line-height:25px"><span style="color:#000080; line-height:25px">Object类的equals方法实现的是对象上差别可能性最大的相等关系:</span><br style="line-height:25px"><span style="color:#000080; line-height:25px">即,对于任何非空引用值x和y,当且仅当x和y引用同一个对象时,</span><br style="line-height:25px"><span style="color:#000080; line-height:25px">此方法才返回true(x==y具有值true)。</span><br style="line-height:25px"><span style="color:#000080; line-height:25px">也就是说equals()方法在object类中定义如下:</span><br style="line-height:25px"><span style="color:#0000ff; line-height:25px">publicbooleanequals(Objectobj){<br style="line-height:25px"> return(this==obj);<br style="line-height:25px"> }</span><br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">对两个对象的地址值进行的比较</wbr></span><wbr style="line-height:25px">(即比较引用是否相同)。<br style="line-height:25px"> 注意1:当此方法被重写时,通常有必要重写hashCode方法,以维护hashCode方法的常规协定,<br style="line-height:25px"> 该协定声明<wbr style="line-height:25px"><span style="color:#0000ff; line-height:25px">相等对象必须具有相等的哈希码</span><wbr style="line-height:25px">。<br style="line-height:25px"> 但是我们必需清楚,当String、Math、还有Integer、Double。。。。等这些封装类在使用equals()方法时,<br style="line-height:25px"> 已经覆盖了object类的equals()方法。比如在String类中如下:<br style="line-height:25px"><span style="color:#993300; line-height:25px">publicboolean</span><span style="color:#ff6600; line-height:25px">equals</span><span style="color:#3366ff; line-height:25px">(ObjectanObject){<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">if</span><span style="color:#3366ff; line-height:25px">(this==anObject){<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">return</span><span style="color:#3366ff; line-height:25px">true;<br style="line-height:25px"> }<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">if</span><span style="color:#3366ff; line-height:25px">(anObject</span><span style="color:#993300; line-height:25px">instanceof</span><span style="color:#3366ff; line-height:25px">String){<br style="line-height:25px"> StringanotherString=(String)anObject;<br style="line-height:25px"> intn=count;<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">if</span><span style="color:#3366ff; line-height:25px">(n==anotherString.count){<br style="line-height:25px"> charv1[]=value;<br style="line-height:25px"> charv2[]=anotherString.value;<br style="line-height:25px"> inti=offset;<br style="line-height:25px"> intj=anotherString.offset;<br style="line-height:25px"> while(n--!=0){<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">if</span><span style="color:#3366ff; line-height:25px">(v1[i++]!=v2[j++])<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">return</span><span style="color:#3366ff; line-height:25px">false;<br style="line-height:25px"> }<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">return</span><span style="color:#3366ff; line-height:25px">true;<br style="line-height:25px"> }<br style="line-height:25px"> }<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">return</span><span style="color:#3366ff; line-height:25px">false;<br style="line-height:25px"> }</span><br style="line-height:25px"><span style="color:#000080; line-height:25px">很明显,</span><span style="color:#ff9900; line-height:25px">这是<wbr style="line-height:25px">进行的内容比较<wbr style="line-height:25px">,而已经不再是地址的比较</wbr></wbr></span><span style="color:#000080; line-height:25px">。依次类推Double、Integer、Math等等这些类都是重写了equals()方法的,</span><br style="line-height:25px"><span style="color:#000080; line-height:25px">从而进行的是内容的比较。当然了基本类型是进行值的比较,这个没有什么好说的。</span><br style="line-height:25px"><wbr style="line-height:25px"><span style="color:#0000ff; line-height:25px">publicinthashCode()</span><br style="line-height:25px"><wbr style="line-height:25px"><span style="color:#000080; line-height:25px">返回该对象的哈希码值。支持该方法是为哈希表提供一些优点,例如,java.util.Hashtable提供的哈希表。</span><br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">hashCode的常规协定</wbr></span><wbr style="line-height:25px">是:<br style="line-height:25px"> *<span style="color:#000080; line-height:25px">在Java应用程序执行期间,在同一对象上多次调用hashCode方法时,必须一致地返回相同的整数,<br style="line-height:25px"> 前提是对象上equals比较中所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,<br style="line-height:25px"> 该整数无需保持一致。</span><br style="line-height:25px"> *<span style="color:#000080; line-height:25px"><wbr style="line-height:25px">如果根据equals(Object)方法,两个对象是相等的,那么在两个对象中的每个对象上调用hashCode方法都必须生成相同的整数结果</wbr></span><wbr style="line-height:25px">。<br style="line-height:25px"> *以下情况<wbr style="line-height:25px"><span style="color:#0000ff; line-height:25px">不是必需</span><wbr style="line-height:25px">的:<span style="color:#000080; line-height:25px">如果根据equals(java.lang.Object)方法,两个对象不相等,<br style="line-height:25px"> 那么在两个对象中的任一对象上调用hashCode方法必定会生成不同的整数结果</span>。<br style="line-height:25px"><span style="color:#000080; line-height:25px">但是,程序员应该知道,为不相等的对象生成不同整数结果可以提高哈希表的性能。</span><br style="line-height:25px"> 实际上,由Object类定义的hashCode方法确实会针对不同的对象返回不同的整数。<br style="line-height:25px"> (这一般是通过将该对象的内部地址转换成一个整数来实现的,但是JavaTM编程语言不需要这种实现技巧。)。<br style="line-height:25px"> 当然我们可以在自己写的类中覆盖hashcode()方法,<br style="line-height:25px"> 比如String、Integer、Double。。。。等等这些类都是覆盖了hashcode()方法的。<br style="line-height:25px"> 例如在String类中定义的hashcode()方法如下:<br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">publicint</span><span style="color:#3366ff; line-height:25px"></span><span style="color:#ff6600; line-height:25px">hashCode</span><span style="color:#3366ff; line-height:25px">(){<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">int</span><span style="color:#3366ff; line-height:25px">h=hash;<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">if</span><span style="color:#3366ff; line-height:25px">(h==0){<br style="line-height:25px"> intoff=offset;<br style="line-height:25px"> charval[]=value;<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">int</span><span style="color:#3366ff; line-height:25px">len=count;<br style="line-height:25px"> for(inti=0;i<len;i++){<br style="line-height:25px"> h=31*h+val[off++];<br style="line-height:25px"> }<br style="line-height:25px"> hash=h;<br style="line-height:25px"> }<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">return</span><span style="color:#3366ff; line-height:25px">h;<br style="line-height:25px"> }</span><br style="line-height:25px"> 解释一下这个程序(String的API中写到):<br style="line-height:25px"><span style="color:#0000ff; line-height:25px">s[0]*31^(n-1)+s[1]*31^(n-2)+...+s[n-1]</span><br style="line-height:25px"> 使用int算法,这里s<wbr style="line-height:25px">是字符串的第i个字符,n是字符串的长度,^表示求幂。(空字符串的哈希码为0。)<br style="line-height:25px"> 这里我们根据hashCode的常规协定首先要明白一个问题:<br style="line-height:25px"><span style="line-height:25px"></span><wbr style="line-height:25px">一,<span style="color:#000080; line-height:25px">equals()相等的两个对象,hashcode()一定相等.</span><br style="line-height:25px"><span style="line-height:25px"></span><wbr style="line-height:25px">二,<span style="color:#000080; line-height:25px">equals()不相等的两个对象,却并不能证明他们的hashcode()不相等<wbr style="line-height:25px">。</wbr></span><br style="line-height:25px"> 换句话说,equals()方法不相等的两个对象,hashcode()有可能相等。(我的理解是由于哈希码在生成的时候产生冲突造成的)。<br style="line-height:25px"> 三,反过来:<wbr style="line-height:25px"><span style="color:#000080; line-height:25px">hashcode()不等,一定能推出equals()也不等</span>(<wbr style="line-height:25px">因为如果equals()相等的话就和第一条矛盾了);<br style="line-height:25px"><wbr style="line-height:25px"><span style="color:#000080; line-height:25px">hashcode()相等,equals()可能相等,也可能不等<wbr style="line-height:25px">。</wbr></span><br style="line-height:25px"><span style="color:#003366; line-height:25px">2.hashset是根据什么原理来存取对象的呢?</span><br style="line-height:25px"> 在hashset中不允许出现重复对象,元素的位置也是不确定的。<br style="line-height:25px"> 在hashset中判断<wbr style="line-height:25px"><span style="color:#000080; line-height:25px">两个对象是否重复</span><wbr style="line-height:25px">的规则是:<br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">1),</wbr></span><span style="color:#000080; line-height:25px">判断两个对象的hashCode是否相等.</span> <div style="line-height:25px"> <span style="color:#000080; line-height:25px"> 如果不相等,认为两个对象也不相等,完毕; 如果相等,转入2)</span><wbr style="line-height:25px"><br style="line-height:25px"> (这一点只是为了提高存储效率而要求的,其实理论上没有也可以,但如果没有,实际使用时效率会大大降低,<br style="line-height:25px"> 所以我们这里将其做为必需的。后面会重点讲到这个问题。)<br style="line-height:25px"> 2),<wbr style="line-height:25px"><span style="color:#000080; line-height:25px">判断两个对象用equals运算是否相等<br style="line-height:25px"> 如果不相等,认为两个对象也不相等; 如果相等,认为两个对象相等</span><wbr style="line-height:25px">(equals()是判断两个对象是否相等的关键)<br style="line-height:25px"><span style="color:#003366; line-height:25px">为什么是两条准则,难道用第一条不行吗?</span><span style="color:#000080; line-height:25px">不行,因为前面已经说了,hashcode()相等时,equals()方法也可能不等,<br style="line-height:25px"> 所以必须用第2条准则进行限制,才能保证加入的为非重复元素</span><span style="color:#003366; line-height:25px">。</span><br style="line-height:25px"><span style="color:#003366; line-height:25px">那么为什么不直接用equals()方法判断呢?</span><br style="line-height:25px"><span style="color:#003366; line-height:25px"></span><span style="color:#000080; line-height:25px">我想是因为效率的原因。很容易让hashcode()的效率比equals()高些,<br style="line-height:25px"> 因为它不必每次都重新算hash值,具体参照上面String的hashcode()实现</span><br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">例1:<br style="line-height:25px"></wbr></span><wbr style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">publicstaticvoid</span><span style="color:#ff6600; line-height:25px">main</span><span style="color:#3366ff; line-height:25px">(Stringargs[]){<br style="line-height:25px"> Strings1=newString("zhaoxudong");<br style="line-height:25px"> Strings2=newString("zhaoxudong");<br style="line-height:25px"> System.out.println(s1==s2);</span><span style="color:#808080; line-height:25px">//false</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">System.out.println(s1.equals(s2));</span><span style="color:#808080; line-height:25px">//true</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">System.out.println(s1.hashCode());</span><span style="color:#808080; line-height:25px">//s1.hashcode()等于s2.hashcode()</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">System.out.println(s2.hashCode());</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">Sethashset=newHashSet();</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">hashset.add(s1);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">hashset.add(s2);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">Iteratorit=hashset.iterator();</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">while</span><span style="color:#3366ff; line-height:25px">(it.hasNext())<br style="line-height:25px"> {<br style="line-height:25px"> System.out.println(it.next());<br style="line-height:25px"> }</span><br style="line-height:25px"> 最后在while循环的时候只打印出了一个”zhaoxudong”。<br style="line-height:25px"> 输出结果为:</wbr></wbr></wbr></wbr> </div> <div style="line-height:25px"><span style="color:#3366ff; line-height:25px">false<br style="line-height:25px"> true<br style="line-height:25px"> -967303459<br style="line-height:25px"> -967303459</span></div> <div style="line-height:25px"> <span style="color:#3366ff; line-height:25px">zhaoxudong</span><br style="line-height:25px"> 这是因为String类已经重写了equals()方法和hashcode()方法,所以在根据上面的第1.2条原则判定时,<br style="line-height:25px"> hashset认为它们是相等的对象,是重复添加。<br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">例2</wbr></span><wbr style="line-height:25px">:<br style="line-height:25px"><span style="color:#3366ff; line-height:25px">importjava.util.*;</span><br style="line-height:25px"><span style="color:#993300; line-height:25px">publicclass</span><span style="color:#3366ff; line-height:25px">HashSetTest<br style="line-height:25px"> {<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">publicstaticvoid</span><span style="color:#3366ff; line-height:25px">main(String[]args)<br style="line-height:25px"> {<br style="line-height:25px"> HashSeths=newHashSet();<br style="line-height:25px"> hs.add(newStudent(1,"zhangsan"));<br style="line-height:25px"> hs.add(newStudent(2,"lisi"));<br style="line-height:25px"> hs.add(newStudent(3,"wangwu"));<br style="line-height:25px"> hs.add(newStudent(1,"zhangsan"));<br style="line-height:25px"><br style="line-height:25px"> Iteratorit=hs.iterator();<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">while</span><span style="color:#3366ff; line-height:25px">(it.hasNext())<br style="line-height:25px"> {<br style="line-height:25px"> System.out.println(it.next());<br style="line-height:25px"> }<br style="line-height:25px"> }<br style="line-height:25px"> }<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">class</span><span style="color:#3366ff; line-height:25px">Student<br style="line-height:25px"> {<br style="line-height:25px"> intnum;<br style="line-height:25px"> Stringname;<br style="line-height:25px"> Student(intnum,Stringname)<br style="line-height:25px"> {<br style="line-height:25px"> this.num=num;<br style="line-height:25px"> this.name=name;<br style="line-height:25px"> }<br style="line-height:25px"> publicStringtoString()<br style="line-height:25px"> {<br style="line-height:25px"> returnnum+":"+name;<br style="line-height:25px"> }<br style="line-height:25px"> }</span><br style="line-height:25px"> 输出结果为:<br style="line-height:25px"><span style="color:#3366ff; line-height:25px">1:zhangsan<br style="line-height:25px"> 1:zhangsan<br style="line-height:25px"> 3:wangwu<br style="line-height:25px"> 2:lisi</span><br style="line-height:25px"> 问题出现了:为什么hashset添加了相等的元素呢,这是不是和hashset的原则违背了呢?回答是:没有<br style="line-height:25px"> 因为在根据hashcode()对两次建立的newStudent(1,"zhangsan")对象进行比较时,生成的是不同的哈希码值,<br style="line-height:25px"> 所以hashset把他当作不同的对象对待了,当然此时的equals()方法返回的值也不等(这个不用解释了吧)。<br style="line-height:25px"> 那么为什么会生成不同的哈希码值呢?原因就在于我们自己写的Student类并没有重写自己的hashcode()和equals()方法,<br style="line-height:25px"> 所以在比较时,是继承的object类中的hashcode()方法,它返回的是和对象地址(引用地址)对应的数,<br style="line-height:25px"> 使用new方法创建对象,两次生成的当然是不同的对象了,造成的结果就是两个对象的hashcode()返回的值不一样。<br style="line-height:25px"> 所以根据第一个准则,hashset会把它们当作不同的对象对待,自然也用不着第二个准则进行判定了。<br style="line-height:25px"> 那么怎么解决这个问题呢?<br style="line-height:25px"> 答案是:在Student类中重新hashcode()和equals()方法。<br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">例3</wbr></span><wbr style="line-height:25px">:<br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">class</span><span style="color:#3366ff; line-height:25px"></span><span style="color:#ff6600; line-height:25px">Student</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">intnum;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">Stringname;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">Student</span><span style="color:#3366ff; line-height:25px">(intnum,Stringname)</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">this.num=num;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">this.name=name;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">publicint</span><span style="color:#3366ff; line-height:25px">hashCode()</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">returnnum*name.hashCode();</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">publicboolean</span><span style="color:#3366ff; line-height:25px">equals(Objecto)</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">Students=(Student)o;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">return</span><span style="color:#3366ff; line-height:25px">num==s.num&&name.equals(s.name);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">public</span><span style="color:#3366ff; line-height:25px">StringtoString()</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">return</span><span style="color:#3366ff; line-height:25px">num+":"+name;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"> 根据重写的方法,即便两次调用了newStudent(1,"zhangsan"),我们在获得对象的哈希码时,获得的哈希码肯定是一样的。<br style="line-height:25px"> 当然根据equals()方法我们也可判断是相同的。所以在向hashset集合中添加时把它们当作重复元素看待了。<br style="line-height:25px"> 所以运行修改后的程序时,我们会发现运行结果是:<br style="line-height:25px"><span style="color:#3366ff; line-height:25px">1:zhangsan<br style="line-height:25px"> 3:wangwu<br style="line-height:25px"> 2:lisi</span><br style="line-height:25px"> 可以看到重复元素的问题已经消除。<br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">例4</wbr></span><wbr style="line-height:25px">:<br style="line-height:25px"><span style="color:#3366ff; line-height:25px">importjava.util.HashSet;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">importjava.util.Random;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">importjava.util.concurrent.SynchronousQueue;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">importjava.util.concurrent.TimeUnit;</span><br style="line-height:25px"><br style="line-height:25px"><span style="color:#993300; line-height:25px">publicclass</span><span style="color:#3366ff; line-height:25px">Test{</span><br style="line-height:25px"><span style="color:#808080; line-height:25px">/**<br style="line-height:25px"> *@paramargs<br style="line-height:25px"> */</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">publicstaticvoid</span><span style="color:#3366ff; line-height:25px"></span><span style="color:#ff6600; line-height:25px">main</span><span style="color:#3366ff; line-height:25px">(String[]args){</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">HashSet<People>set=newHashSet();</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">set.add(newPeople("robin",1,21));</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">set.add(newPeople("hb",2,20));</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">set.add(newPeople("harry",3,30));</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">set.add(null);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">Peoplep4=newPeople("robin",4,25);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">set.add(p4);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">set.add(newPeople("yp",5,28));</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">for(Peoplep:set)</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">System.out.println(p);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#993300; line-height:25px">class</span><span style="color:#ff6600; line-height:25px">People</span><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">Stringname;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">intid;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">intage;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">public</span><span style="color:#3366ff; line-height:25px">People(Stringname,intid)</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">this(name,id,0);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">public</span><span style="color:#3366ff; line-height:25px">People(Stringname,intid,intage)</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">this.name=name;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">this.id=id;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">this.age=age;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">public</span><span style="color:#3366ff; line-height:25px">StringtoString()</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">returnid+name+age;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">publicboolean</span><span style="color:#3366ff; line-height:25px">equals(Objecto)</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">if(o==null)</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">returnfalse;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">if(!(oinstanceofPeople))</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">returnfalse;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">Peoplep=(People)o;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">booleanres=name.equals(p.name);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">if(res)</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">System.out.println("name"+name+"isdouble");</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">else</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">System.out.println(name+"vS"+p.name);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">returnres;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">publicint</span><span style="color:#3366ff; line-height:25px">hashCode()</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">return</span><span style="color:#3366ff; line-height:25px">name.hashCode();</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"> 结果:</wbr></wbr></wbr> </div> <div style="line-height:25px"> <span style="color:#3366ff; line-height:25px">namerobinisdouble</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">null<br style="line-height:25px"> 1robin21<br style="line-height:25px"> 3harry30<br style="line-height:25px"> 5yp28<br style="line-height:25px"> 2hb20</span><br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">注意1:</wbr></span>当试图添加一个重复元素到hashset时,新元素并不会把旧元素替换掉,<br style="line-height:25px"> 而只是新元素不会添加到hashset(不会抛异常。)<wbr style="line-height:25px"><br style="line-height:25px"></wbr> </div> </wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr style="line-height:25px">1.</wbr>首先equals()和hashcode()这两个方法都是从object类中继承过来的。
publicbooleanequals(Objectobj)
<wbr style="line-height:25px">指示某个其他对象是否与此对象“相等”。<br style="line-height:25px"><span style="line-height:25px"><span style="color:#003366; line-height:25px"><wbr style="line-height:25px">equals方法在非空对象引用上实现相等关系<wbr style="line-height:25px">:</wbr></wbr></span></span><br style="line-height:25px"> *<span style="line-height:25px"><wbr style="line-height:25px">自反性</wbr></span><wbr style="line-height:25px">:对于任何非空引用值x,x.equals(x)都应返回true。<br style="line-height:25px"> *<span style="line-height:25px"><wbr style="line-height:25px">对称性</wbr></span><wbr style="line-height:25px">:对于任何非空引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)才应返回true。<br style="line-height:25px"> *<span style="line-height:25px"><wbr style="line-height:25px">传递性</wbr></span><wbr style="line-height:25px">:对于任何非空引用值x、y和z,如果x.equals(y)返回true,<br style="line-height:25px"> 并且y.equals(z)返回true,那么x.equals(z)应返回true。<br style="line-height:25px"> *<span style="line-height:25px"><wbr style="line-height:25px">一致性:对于任何非空引用值x和y,多次调用x.equals(y)始终返回true或始终返回false,<br style="line-height:25px"> 前</wbr></span><wbr style="line-height:25px">提是对象上equals比较中所用的信息没有被修改。<br style="line-height:25px"> *<span style="line-height:25px"><wbr style="line-height:25px">对于任何非空引用值</wbr></span><wbr style="line-height:25px">x,x.equals(null)都应返回false。<br style="line-height:25px"> 注意:以上这五点是重写equals()方法时,<wbr style="line-height:25px"><span style="color:#0000ff; line-height:25px">必须遵守的准则</span><wbr style="line-height:25px">,如果违反会出现意想不到的结果<br style="line-height:25px"><span style="color:#000080; line-height:25px">Object类的equals方法实现的是对象上差别可能性最大的相等关系:</span><br style="line-height:25px"><span style="color:#000080; line-height:25px">即,对于任何非空引用值x和y,当且仅当x和y引用同一个对象时,</span><br style="line-height:25px"><span style="color:#000080; line-height:25px">此方法才返回true(x==y具有值true)。</span><br style="line-height:25px"><span style="color:#000080; line-height:25px">也就是说equals()方法在object类中定义如下:</span><br style="line-height:25px"><span style="color:#0000ff; line-height:25px">publicbooleanequals(Objectobj){<br style="line-height:25px"> return(this==obj);<br style="line-height:25px"> }</span><br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">对两个对象的地址值进行的比较</wbr></span><wbr style="line-height:25px">(即比较引用是否相同)。<br style="line-height:25px"> 注意1:当此方法被重写时,通常有必要重写hashCode方法,以维护hashCode方法的常规协定,<br style="line-height:25px"> 该协定声明<wbr style="line-height:25px"><span style="color:#0000ff; line-height:25px">相等对象必须具有相等的哈希码</span><wbr style="line-height:25px">。<br style="line-height:25px"> 但是我们必需清楚,当String、Math、还有Integer、Double。。。。等这些封装类在使用equals()方法时,<br style="line-height:25px"> 已经覆盖了object类的equals()方法。比如在String类中如下:<br style="line-height:25px"><span style="color:#993300; line-height:25px">publicboolean</span><span style="color:#ff6600; line-height:25px">equals</span><span style="color:#3366ff; line-height:25px">(ObjectanObject){<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">if</span><span style="color:#3366ff; line-height:25px">(this==anObject){<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">return</span><span style="color:#3366ff; line-height:25px">true;<br style="line-height:25px"> }<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">if</span><span style="color:#3366ff; line-height:25px">(anObject</span><span style="color:#993300; line-height:25px">instanceof</span><span style="color:#3366ff; line-height:25px">String){<br style="line-height:25px"> StringanotherString=(String)anObject;<br style="line-height:25px"> intn=count;<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">if</span><span style="color:#3366ff; line-height:25px">(n==anotherString.count){<br style="line-height:25px"> charv1[]=value;<br style="line-height:25px"> charv2[]=anotherString.value;<br style="line-height:25px"> inti=offset;<br style="line-height:25px"> intj=anotherString.offset;<br style="line-height:25px"> while(n--!=0){<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">if</span><span style="color:#3366ff; line-height:25px">(v1[i++]!=v2[j++])<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">return</span><span style="color:#3366ff; line-height:25px">false;<br style="line-height:25px"> }<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">return</span><span style="color:#3366ff; line-height:25px">true;<br style="line-height:25px"> }<br style="line-height:25px"> }<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">return</span><span style="color:#3366ff; line-height:25px">false;<br style="line-height:25px"> }</span><br style="line-height:25px"><span style="color:#000080; line-height:25px">很明显,</span><span style="color:#ff9900; line-height:25px">这是<wbr style="line-height:25px">进行的内容比较<wbr style="line-height:25px">,而已经不再是地址的比较</wbr></wbr></span><span style="color:#000080; line-height:25px">。依次类推Double、Integer、Math等等这些类都是重写了equals()方法的,</span><br style="line-height:25px"><span style="color:#000080; line-height:25px">从而进行的是内容的比较。当然了基本类型是进行值的比较,这个没有什么好说的。</span><br style="line-height:25px"><wbr style="line-height:25px"><span style="color:#0000ff; line-height:25px">publicinthashCode()</span><br style="line-height:25px"><wbr style="line-height:25px"><span style="color:#000080; line-height:25px">返回该对象的哈希码值。支持该方法是为哈希表提供一些优点,例如,java.util.Hashtable提供的哈希表。</span><br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">hashCode的常规协定</wbr></span><wbr style="line-height:25px">是:<br style="line-height:25px"> *<span style="color:#000080; line-height:25px">在Java应用程序执行期间,在同一对象上多次调用hashCode方法时,必须一致地返回相同的整数,<br style="line-height:25px"> 前提是对象上equals比较中所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,<br style="line-height:25px"> 该整数无需保持一致。</span><br style="line-height:25px"> *<span style="color:#000080; line-height:25px"><wbr style="line-height:25px">如果根据equals(Object)方法,两个对象是相等的,那么在两个对象中的每个对象上调用hashCode方法都必须生成相同的整数结果</wbr></span><wbr style="line-height:25px">。<br style="line-height:25px"> *以下情况<wbr style="line-height:25px"><span style="color:#0000ff; line-height:25px">不是必需</span><wbr style="line-height:25px">的:<span style="color:#000080; line-height:25px">如果根据equals(java.lang.Object)方法,两个对象不相等,<br style="line-height:25px"> 那么在两个对象中的任一对象上调用hashCode方法必定会生成不同的整数结果</span>。<br style="line-height:25px"><span style="color:#000080; line-height:25px">但是,程序员应该知道,为不相等的对象生成不同整数结果可以提高哈希表的性能。</span><br style="line-height:25px"> 实际上,由Object类定义的hashCode方法确实会针对不同的对象返回不同的整数。<br style="line-height:25px"> (这一般是通过将该对象的内部地址转换成一个整数来实现的,但是JavaTM编程语言不需要这种实现技巧。)。<br style="line-height:25px"> 当然我们可以在自己写的类中覆盖hashcode()方法,<br style="line-height:25px"> 比如String、Integer、Double。。。。等等这些类都是覆盖了hashcode()方法的。<br style="line-height:25px"> 例如在String类中定义的hashcode()方法如下:<br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">publicint</span><span style="color:#3366ff; line-height:25px"></span><span style="color:#ff6600; line-height:25px">hashCode</span><span style="color:#3366ff; line-height:25px">(){<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">int</span><span style="color:#3366ff; line-height:25px">h=hash;<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">if</span><span style="color:#3366ff; line-height:25px">(h==0){<br style="line-height:25px"> intoff=offset;<br style="line-height:25px"> charval[]=value;<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">int</span><span style="color:#3366ff; line-height:25px">len=count;<br style="line-height:25px"> for(inti=0;i<len;i++){<br style="line-height:25px"> h=31*h+val[off++];<br style="line-height:25px"> }<br style="line-height:25px"> hash=h;<br style="line-height:25px"> }<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">return</span><span style="color:#3366ff; line-height:25px">h;<br style="line-height:25px"> }</span><br style="line-height:25px"> 解释一下这个程序(String的API中写到):<br style="line-height:25px"><span style="color:#0000ff; line-height:25px">s[0]*31^(n-1)+s[1]*31^(n-2)+...+s[n-1]</span><br style="line-height:25px"> 使用int算法,这里s<wbr style="line-height:25px">是字符串的第i个字符,n是字符串的长度,^表示求幂。(空字符串的哈希码为0。)<br style="line-height:25px"> 这里我们根据hashCode的常规协定首先要明白一个问题:<br style="line-height:25px"><span style="line-height:25px"></span><wbr style="line-height:25px">一,<span style="color:#000080; line-height:25px">equals()相等的两个对象,hashcode()一定相等.</span><br style="line-height:25px"><span style="line-height:25px"></span><wbr style="line-height:25px">二,<span style="color:#000080; line-height:25px">equals()不相等的两个对象,却并不能证明他们的hashcode()不相等<wbr style="line-height:25px">。</wbr></span><br style="line-height:25px"> 换句话说,equals()方法不相等的两个对象,hashcode()有可能相等。(我的理解是由于哈希码在生成的时候产生冲突造成的)。<br style="line-height:25px"> 三,反过来:<wbr style="line-height:25px"><span style="color:#000080; line-height:25px">hashcode()不等,一定能推出equals()也不等</span>(<wbr style="line-height:25px">因为如果equals()相等的话就和第一条矛盾了);<br style="line-height:25px"><wbr style="line-height:25px"><span style="color:#000080; line-height:25px">hashcode()相等,equals()可能相等,也可能不等<wbr style="line-height:25px">。</wbr></span><br style="line-height:25px"><span style="color:#003366; line-height:25px">2.hashset是根据什么原理来存取对象的呢?</span><br style="line-height:25px"> 在hashset中不允许出现重复对象,元素的位置也是不确定的。<br style="line-height:25px"> 在hashset中判断<wbr style="line-height:25px"><span style="color:#000080; line-height:25px">两个对象是否重复</span><wbr style="line-height:25px">的规则是:<br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">1),</wbr></span><span style="color:#000080; line-height:25px">判断两个对象的hashCode是否相等.</span> <div style="line-height:25px"> <span style="color:#000080; line-height:25px"> 如果不相等,认为两个对象也不相等,完毕; 如果相等,转入2)</span><wbr style="line-height:25px"><br style="line-height:25px"> (这一点只是为了提高存储效率而要求的,其实理论上没有也可以,但如果没有,实际使用时效率会大大降低,<br style="line-height:25px"> 所以我们这里将其做为必需的。后面会重点讲到这个问题。)<br style="line-height:25px"> 2),<wbr style="line-height:25px"><span style="color:#000080; line-height:25px">判断两个对象用equals运算是否相等<br style="line-height:25px"> 如果不相等,认为两个对象也不相等; 如果相等,认为两个对象相等</span><wbr style="line-height:25px">(equals()是判断两个对象是否相等的关键)<br style="line-height:25px"><span style="color:#003366; line-height:25px">为什么是两条准则,难道用第一条不行吗?</span><span style="color:#000080; line-height:25px">不行,因为前面已经说了,hashcode()相等时,equals()方法也可能不等,<br style="line-height:25px"> 所以必须用第2条准则进行限制,才能保证加入的为非重复元素</span><span style="color:#003366; line-height:25px">。</span><br style="line-height:25px"><span style="color:#003366; line-height:25px">那么为什么不直接用equals()方法判断呢?</span><br style="line-height:25px"><span style="color:#003366; line-height:25px"></span><span style="color:#000080; line-height:25px">我想是因为效率的原因。很容易让hashcode()的效率比equals()高些,<br style="line-height:25px"> 因为它不必每次都重新算hash值,具体参照上面String的hashcode()实现</span><br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">例1:<br style="line-height:25px"></wbr></span><wbr style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">publicstaticvoid</span><span style="color:#ff6600; line-height:25px">main</span><span style="color:#3366ff; line-height:25px">(Stringargs[]){<br style="line-height:25px"> Strings1=newString("zhaoxudong");<br style="line-height:25px"> Strings2=newString("zhaoxudong");<br style="line-height:25px"> System.out.println(s1==s2);</span><span style="color:#808080; line-height:25px">//false</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">System.out.println(s1.equals(s2));</span><span style="color:#808080; line-height:25px">//true</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">System.out.println(s1.hashCode());</span><span style="color:#808080; line-height:25px">//s1.hashcode()等于s2.hashcode()</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">System.out.println(s2.hashCode());</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">Sethashset=newHashSet();</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">hashset.add(s1);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">hashset.add(s2);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">Iteratorit=hashset.iterator();</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">while</span><span style="color:#3366ff; line-height:25px">(it.hasNext())<br style="line-height:25px"> {<br style="line-height:25px"> System.out.println(it.next());<br style="line-height:25px"> }</span><br style="line-height:25px"> 最后在while循环的时候只打印出了一个”zhaoxudong”。<br style="line-height:25px"> 输出结果为:</wbr></wbr></wbr></wbr> </div> <div style="line-height:25px"><span style="color:#3366ff; line-height:25px">false<br style="line-height:25px"> true<br style="line-height:25px"> -967303459<br style="line-height:25px"> -967303459</span></div> <div style="line-height:25px"> <span style="color:#3366ff; line-height:25px">zhaoxudong</span><br style="line-height:25px"> 这是因为String类已经重写了equals()方法和hashcode()方法,所以在根据上面的第1.2条原则判定时,<br style="line-height:25px"> hashset认为它们是相等的对象,是重复添加。<br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">例2</wbr></span><wbr style="line-height:25px">:<br style="line-height:25px"><span style="color:#3366ff; line-height:25px">importjava.util.*;</span><br style="line-height:25px"><span style="color:#993300; line-height:25px">publicclass</span><span style="color:#3366ff; line-height:25px">HashSetTest<br style="line-height:25px"> {<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">publicstaticvoid</span><span style="color:#3366ff; line-height:25px">main(String[]args)<br style="line-height:25px"> {<br style="line-height:25px"> HashSeths=newHashSet();<br style="line-height:25px"> hs.add(newStudent(1,"zhangsan"));<br style="line-height:25px"> hs.add(newStudent(2,"lisi"));<br style="line-height:25px"> hs.add(newStudent(3,"wangwu"));<br style="line-height:25px"> hs.add(newStudent(1,"zhangsan"));<br style="line-height:25px"><br style="line-height:25px"> Iteratorit=hs.iterator();<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">while</span><span style="color:#3366ff; line-height:25px">(it.hasNext())<br style="line-height:25px"> {<br style="line-height:25px"> System.out.println(it.next());<br style="line-height:25px"> }<br style="line-height:25px"> }<br style="line-height:25px"> }<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">class</span><span style="color:#3366ff; line-height:25px">Student<br style="line-height:25px"> {<br style="line-height:25px"> intnum;<br style="line-height:25px"> Stringname;<br style="line-height:25px"> Student(intnum,Stringname)<br style="line-height:25px"> {<br style="line-height:25px"> this.num=num;<br style="line-height:25px"> this.name=name;<br style="line-height:25px"> }<br style="line-height:25px"> publicStringtoString()<br style="line-height:25px"> {<br style="line-height:25px"> returnnum+":"+name;<br style="line-height:25px"> }<br style="line-height:25px"> }</span><br style="line-height:25px"> 输出结果为:<br style="line-height:25px"><span style="color:#3366ff; line-height:25px">1:zhangsan<br style="line-height:25px"> 1:zhangsan<br style="line-height:25px"> 3:wangwu<br style="line-height:25px"> 2:lisi</span><br style="line-height:25px"> 问题出现了:为什么hashset添加了相等的元素呢,这是不是和hashset的原则违背了呢?回答是:没有<br style="line-height:25px"> 因为在根据hashcode()对两次建立的newStudent(1,"zhangsan")对象进行比较时,生成的是不同的哈希码值,<br style="line-height:25px"> 所以hashset把他当作不同的对象对待了,当然此时的equals()方法返回的值也不等(这个不用解释了吧)。<br style="line-height:25px"> 那么为什么会生成不同的哈希码值呢?原因就在于我们自己写的Student类并没有重写自己的hashcode()和equals()方法,<br style="line-height:25px"> 所以在比较时,是继承的object类中的hashcode()方法,它返回的是和对象地址(引用地址)对应的数,<br style="line-height:25px"> 使用new方法创建对象,两次生成的当然是不同的对象了,造成的结果就是两个对象的hashcode()返回的值不一样。<br style="line-height:25px"> 所以根据第一个准则,hashset会把它们当作不同的对象对待,自然也用不着第二个准则进行判定了。<br style="line-height:25px"> 那么怎么解决这个问题呢?<br style="line-height:25px"> 答案是:在Student类中重新hashcode()和equals()方法。<br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">例3</wbr></span><wbr style="line-height:25px">:<br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">class</span><span style="color:#3366ff; line-height:25px"></span><span style="color:#ff6600; line-height:25px">Student</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">intnum;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">Stringname;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">Student</span><span style="color:#3366ff; line-height:25px">(intnum,Stringname)</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">this.num=num;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">this.name=name;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">publicint</span><span style="color:#3366ff; line-height:25px">hashCode()</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">returnnum*name.hashCode();</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">publicboolean</span><span style="color:#3366ff; line-height:25px">equals(Objecto)</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">Students=(Student)o;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">return</span><span style="color:#3366ff; line-height:25px">num==s.num&&name.equals(s.name);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">public</span><span style="color:#3366ff; line-height:25px">StringtoString()</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">return</span><span style="color:#3366ff; line-height:25px">num+":"+name;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"> 根据重写的方法,即便两次调用了newStudent(1,"zhangsan"),我们在获得对象的哈希码时,获得的哈希码肯定是一样的。<br style="line-height:25px"> 当然根据equals()方法我们也可判断是相同的。所以在向hashset集合中添加时把它们当作重复元素看待了。<br style="line-height:25px"> 所以运行修改后的程序时,我们会发现运行结果是:<br style="line-height:25px"><span style="color:#3366ff; line-height:25px">1:zhangsan<br style="line-height:25px"> 3:wangwu<br style="line-height:25px"> 2:lisi</span><br style="line-height:25px"> 可以看到重复元素的问题已经消除。<br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">例4</wbr></span><wbr style="line-height:25px">:<br style="line-height:25px"><span style="color:#3366ff; line-height:25px">importjava.util.HashSet;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">importjava.util.Random;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">importjava.util.concurrent.SynchronousQueue;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">importjava.util.concurrent.TimeUnit;</span><br style="line-height:25px"><br style="line-height:25px"><span style="color:#993300; line-height:25px">publicclass</span><span style="color:#3366ff; line-height:25px">Test{</span><br style="line-height:25px"><span style="color:#808080; line-height:25px">/**<br style="line-height:25px"> *@paramargs<br style="line-height:25px"> */</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">publicstaticvoid</span><span style="color:#3366ff; line-height:25px"></span><span style="color:#ff6600; line-height:25px">main</span><span style="color:#3366ff; line-height:25px">(String[]args){</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">HashSet<People>set=newHashSet();</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">set.add(newPeople("robin",1,21));</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">set.add(newPeople("hb",2,20));</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">set.add(newPeople("harry",3,30));</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">set.add(null);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">Peoplep4=newPeople("robin",4,25);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">set.add(p4);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">set.add(newPeople("yp",5,28));</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">for(Peoplep:set)</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">System.out.println(p);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#993300; line-height:25px">class</span><span style="color:#ff6600; line-height:25px">People</span><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">Stringname;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">intid;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">intage;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">public</span><span style="color:#3366ff; line-height:25px">People(Stringname,intid)</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">this(name,id,0);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">public</span><span style="color:#3366ff; line-height:25px">People(Stringname,intid,intage)</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">this.name=name;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">this.id=id;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">this.age=age;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">public</span><span style="color:#3366ff; line-height:25px">StringtoString()</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">returnid+name+age;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">publicboolean</span><span style="color:#3366ff; line-height:25px">equals(Objecto)</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">if(o==null)</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">returnfalse;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">if(!(oinstanceofPeople))</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">returnfalse;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">Peoplep=(People)o;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">booleanres=name.equals(p.name);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">if(res)</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">System.out.println("name"+name+"isdouble");</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">else</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">System.out.println(name+"vS"+p.name);</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">returnres;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">publicint</span><span style="color:#3366ff; line-height:25px">hashCode()</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">return</span><span style="color:#3366ff; line-height:25px">name.hashCode();</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"> 结果:</wbr></wbr></wbr> </div> <div style="line-height:25px"> <span style="color:#3366ff; line-height:25px">namerobinisdouble</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">null<br style="line-height:25px"> 1robin21<br style="line-height:25px"> 3harry30<br style="line-height:25px"> 5yp28<br style="line-height:25px"> 2hb20</span><br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">注意1:</wbr></span>当试图添加一个重复元素到hashset时,新元素并不会把旧元素替换掉,<br style="line-height:25px"> 而只是新元素不会添加到hashset(不会抛异常。)<wbr style="line-height:25px"><br style="line-height:25px"></wbr> </div> </wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>