黑马程序员技术交流社区

标题: 在HashSet中怎么去除重复的元素啊? [打印本页]

作者: Zhang_qian    时间: 2012-5-11 18:22
标题: 在HashSet中怎么去除重复的元素啊?
import java.util.*;
class HashSetDemo
{
        public static void main(String[] args)
        {
                HashSet ha=new HashSet();
              ha.add(new Person("张三",22));
                  ha.add(new Person("李思",23));
                  ha.add(new Person("王五",24));
                  ha.add(new Person("李思",23));
                  ha.add(new Person("王五",24));
                 // sop(ha);
            Iterator it=ha.iterator();
                while(it.hasNext())
                {
                        Person p=(Person)it.next();
                        sop("姓名:"+p.getName()+"年龄:"+p.getAge());
                }
        }
        public static void sop(Object obj)
        {
                System.out.println(obj);
        }
}
class Person
{
        private String name;
        private int age;
    Person(String name,int age)
        {
                this.name=name;
                this.age=age;
        }
        public String getName()
        {
                return name;
        }
        public int getAge()
        {
                return age;
        }
        public boolean equals(Object obj)
        {
                if(!(obj instanceof Person))
                        return false;
                Person p=(Person)obj;
                return this.name.equals(p.name) && this.age==p.age;
        }
       
}这里有点迷糊请高手指点讲讲在底层是怎么运行的???
作者: 李啸    时间: 2012-5-11 18:26
在Person类中重写hashcode()方法 不用自己去写代码自动生成的即可(hashcode()方法建议自动生成和自己手写的区别不大)
作者: 付信榕    时间: 2012-5-11 18:40
首先Set集合(HashSet和TreeSet)的特点是:无序,不可以有重复元素。HashSet集合保证元素唯一性是这样的,在hashcode()方法中调用equals()方法来判断两元素的hash值是否相同,相同则认为重复元素不插入,否则插入。这里覆盖了equals()方法,告诉jvm,现在相同元素的条件变为了this.name.equals(p.name) && this.age==p.age;(姓名,年龄相同才是同一人),这样就能保证Person对象不重复了。否则保证不了,因为不同Person对象hsah值不相同。
作者: 陈忠    时间: 2012-5-11 19:05
set集合的特点,无序不可重复。
hashset是一个实现了set接口的子类。底层的数据结构式哈希表。当你在此集合中添加自定义对象时,必须要复写hashcode方法和equals方法。

不可重复,实际就是调用对象的equals方法。比较对象是否相等。首先会比较两对象的哈希值是否相同。根据该值来得到一个位置用来存放当前对象,当在该位置没有一个对象存在的话,那么集合Set认为该对象在集合中不存在,直接增加进去。如果在该位置有一个对象存在的话,接着将准备增加到集合中的对象与该位置上的对象进行equals方法比较,如果该equals方法返回false,那么集合认为集合中不存在该对象,在进行一次散列,将该对象放到散列后计算出的新地址里,如果equals方法返回true,那么集合认为集合中已经存在该对象了,不会再将该对象增加到集合中了

就是这样了,希望对你有帮助!
作者: 杨威    时间: 2012-5-11 19:09
前提是set集合中元素是无序的,元素的存与取也是不一定一致的。而hashset底层数据结构是哈希表
hashset是如何保证元素的唯一性的呢
针对你这个程序我来说一下
HashSet ha=new HashSet();
ha.add(new Person("张三",22));
ha.add(new Person("李思",23));
ha.add(new Person("王五",24));
ha.add(new Person("李思",23));
ha.add(new Person("王五",24));
这里new了五个对象,他们的hash值是不同的,new一个对象就会有对应的hash值,是不同的。所以都会存入,(原因是你并没有复写hashcode方法),当你复写了hashcode方法后,相应语句是:
public int hashCode()
{
    return naem.hashCode()+age*34;
}
复写后,上面的五个元素在添加时只要重复了,那复写后得到的hashcode值肯定是相同的了,这是他就会再来调用equals方法来比较元素自身的相等性,如果不相等在相等hashCode值处延伸一个位置,并存储这个值,如果相等,就认为是相同元素,就不会存入。就保证了元素的唯一性。
也就是说,它通过两步来完成元素唯一的存储:
1,先判断元素hashcode值是否相同,如不同存入,如相同再进入下一步
2,判断equals结果,为true,说明完全相等,不存,否则存入。
视频中毕老师有画图,讲解的比较细,建议你好好看看





作者: 黄坚声    时间: 2012-5-11 19:12
我觉得举个例子给你看比较好理解。请看:

下面这个例子,第一次打印结果为1,可以理解,因为HashSet不添加重复的值,
但是第二个例子,打印结果为10,为什么呢,注意class   V已经复写了equals方法了。


class   V{
int   i;
public   V(int   i)
{this.i=i;}

public   int   getI()
{return   this.i;}

public   boolean   equals(Object   o)
{
V   v=(V)o;
System.out.println(v.getI()==this.i);
return   v.getI()==this.i;
}
public   int   compareTo(Object   o){
V   v=(V)o;
if   (v.getI()> this.i)
return   -1;
else   if(v.getI() <this.i)
return   1;
return   0;
}

}

public   class   Test{
public   static   void   main(String[]   args)
{
            HashSet   set=new   HashSet();
            for(int   i=0;   i <10;   i++)
                  set.add(new   String(“test”));
System.out.println(set.size());
            for   (int   i=0;   i <10;   i++)
          {set.add(new   V(1));}
  System.out.println(set.size());
         

        
}
}

作者: 韩新凯    时间: 2012-5-11 22:10
public int hashCode()
{
    return name.hashCode()+age*34;
}





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