黑马程序员技术交流社区

标题: 关于一个Set集合的问题 [打印本页]

作者: 在乎..    时间: 2013-7-19 00:59
标题: 关于一个Set集合的问题
class abc{
        private int a;
        public abc(int i){
                this.a=i;
        }
        public int hashCode(){
                return 1;
        }
        public boolean equals(){
                if(this.a==1)
                {
                return true;}
                else
                        return false;
               
        }
}

...
abc a=new abc(5);          abc b=new abc(1);          abc c=new abc(5);          Collection<abc> c1=new HashSet<abc>();          c1.add(a);          c1.add(b);          c1.add(c);         System.out.println(c1.size());    //打印是3 ,为什么b还能存进去?不是太懂


作者: a767175432    时间: 2013-7-19 01:25
b是添加不进去的,你现在添加进去了是因为equals(Object o)没有被重写,你这是重载所以会添加进入
还有建议编码风格需要改正,类名大写
作者: 周之浩    时间: 2013-7-19 08:20
本帖最后由 周之浩 于 2013-7-19 08:23 编辑

hashSet中不能存放两个用equals(重写父类Object类的equals(Object obj))比较相等的值,如果两个对象用equals比较为true则只能放入一个对象,后放入的对象被丢掉而你的程序中没有用equals方法比较相同的两个对象,可以看看我写的小例子如果不懂我再给你讲讲
  1. package com.ccit;

  2. import java.util.Collection;
  3. import java.util.HashSet;

  4. public class HashTest {

  5.         public static void main(String[] args) {
  6.                 // TODO Auto-generated method stub
  7.         Collection<People> coll = new HashSet<People>();
  8.         People p1 = new People("zhou", 22, "男");
  9.         People p2 = new People("zhan", 25, "女");
  10.         People p3 = new People("lisi", 26, "男");
  11.         People p5 = new People("zhou", 28, "女");
  12.         People p4 = new People("zhou", 22, "男");
  13.         coll.add(p1);
  14.         coll.add(p2);
  15.         coll.add(p3);
  16.         coll.add(p4);
  17.         coll.add(p5);
  18.         System.out.println(coll.size());
  19.         for(People p : coll)
  20.         {
  21.                 System.out.println(p);
  22.         }
  23.         }

  24. }

  25. class People
  26. {
  27.         private String name;
  28.         private int age;
  29.         private String sex;
  30.         
  31.         public People(String name,int age,String sex)
  32.         {
  33.                 this.name = name;
  34.                 this.age = age;
  35.                 this.sex = sex;
  36.         }

  37.         @Override
  38.         public boolean equals(Object obj) {
  39.                 boolean flag = false;
  40.                 if(obj instanceof People)
  41.                 {
  42.                         People p1 = (People)obj;
  43.                         if(this.hashCode() == p1.hashCode())
  44.                          flag = true;
  45.                 }
  46.                 return flag;
  47.         }

  48.         @Override
  49.         public int hashCode() {
  50.                 return name.hashCode()+sex.hashCode()+age;
  51.         }

  52.         @Override
  53.         public String toString() {
  54.                 // TODO Auto-generated method stub
  55.                 return this.name+"\t"+this.age+"\t"+this.sex;
  56.         }
  57.         
  58.         
  59. }
复制代码

作者: 肥猫    时间: 2013-7-19 08:47
本帖最后由 肥猫 于 2013-7-19 08:58 编辑

关键就在于你的3个NEW,而且你的EQUALS方法的重写是重点。当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。
如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,
就调用它的equals方法与新元素进行比较,相同的话就不存了,{不相同就散列其它的地址。},最主要的是:{你的EQUALS方法重写的有问题,比较对象属性是否为1?这里因该用来比较两个对象才对,你这么做就是JVM就默认了两个对象为FALSE了,因为BOOLEAN默认的EQUALS去比较了。相当与你那EQUALS方法是废的,就是这样。}这就是为什么会有3个的原因了。
再清楚点说HASHCODE值只是用来分配存储空间地址和查询用的,主要的判定还是EQUALS。


作者: Mr_Free    时间: 2013-7-27 22:28
  1. package cn.itcast.day3;

  2. import java.util.Collection;
  3. import java.util.HashSet;
  4. import java.util.Iterator;

  5. public class hashProblem {
  6.         public static void main(String[] args){
  7.         Abc a=new Abc(5);
  8.         Abc b=new Abc(1);
  9.         Abc c=new Abc(5);
  10.         Collection<Abc> c1=new HashSet<Abc>();         
  11.         c1.add(a);         
  12.         c1.add(b);         
  13.         c1.add(c);        
  14.         Iterator it = c1.iterator();
  15.         while(it.hasNext()){
  16.                 Abc abc = (Abc)it.next();
  17.                 System.out.println("get对象的a值"+abc.getA());
  18.         }
  19.         
  20.         System.out.println(c1.size());  }
  21. }

  22. class Abc{
  23.         private int a;
  24.         public Abc(int i){
  25.             this.a=i;
  26.     }
  27.         public int  getA()
  28.         {
  29.                 return this.a;
  30.         }
  31.   
  32.         public int hashCode(){
  33.                 return 1;
  34.         }
  35.         public boolean equals(Object obj){
  36.                 Abc ab =(Abc)obj;
  37.                 if(ab.a==1)
  38.                 {
  39.                         return true;
  40.                 }
  41.                 else
  42.                 return false;
  43.                
  44.         }

  45. }
复制代码
我帮你把代码改了下,问题出在equals方法上面 因为你这里用的equal()里面没有写参数,所以没有覆盖Object的方法,所以就不能按照你的方法判断。b写进去的原因是你new了3次,内存创建3次地址空间,这3个对象分别指向3个地址空间,所以肯定不相等,然后就存进去了。
作者: sergio    时间: 2013-7-29 20:05
{:soso_e136:}hashCode()中最好不要写固定值返回值,写的固定值的话,挂在同一个单向链表下,数据不能均匀分布也就起不到增删效果了,要均衡分布,最好像这样:a.hashCode()获取当前变量的哈希值来增加元素。
第二个:equals()方法写的有些问题。如下的你可以参考下:
  1.         public boolean equals(Object o)
  2.         {
  3.                 if(this == o)
  4.                 {
  5.                         return true;
  6.                 }
  7.                 if(o instanceof abc)
  8.                 {
  9.                         abc aABC = (abc)o;
  10.                         if(aABC.a.equals(this.a))
  11.                         {
  12.                                 return true;
  13.                         }
  14.                 }               
  15.                 return false;
  16.         }
复制代码





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2