黑马程序员技术交流社区

标题: 求高手指教:Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? [打印本页]

作者: 王小丑    时间: 2013-2-12 16:20
标题: 求高手指教:Set里的元素是不能重复的,那么用什么方法来区分重复与否呢?
有一个小问题,一直困扰我,就是Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别? 求大师给举出个例子最好!多谢!
作者: 冯佩    时间: 2013-2-12 17:47
Set集合分为HashSet和TreeSet,HashSet底层是哈希表结构,其保证元素的唯一性是通过元素的两个方法hashCode和equals来完成的,如果元素的hashCode值相同,才会判断equals是否为true.如果元素的hashCode值不同,不会调用equals。TreeSet底层数据结构是二叉树。保证元素唯一性的依据是compareTo方法return 0.第一,要确定是哪种Set集合,第二,定义元素唯一性的依据同样也是判断元素是否重复的方法。
作者: 沈文杰    时间: 2013-2-12 19:49
举一个例子:你可以定义一个学生类,然后把学生类的的hashcode方法复写,让hash值固定为37(随便定),然后将学生类存储到HashSet集合中。若不复写equals值,则只能存进一个学生对象,若改写则可以存储多个。这就说明HashSet底层先调用hash值判断是不是同一个对象,若Hash值相同则调用自定义的equals再比较一次。
作者: 王勇文    时间: 2013-2-12 20:04
不知道你的问题重点是哪里。Se集合t的话楼上说的很清楚了hashSet用hashcode()和equals()方法比较是否重复。
TreeSet用compare()和compareTo()方法保证元素的唯一性。   所以Set集合里是不使用== 来保证元素的唯一性的。

java中equals和==的区别   值类型是存储在内存中的堆栈(以后简称栈),而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而其本身则存储在堆中。
    ==操作比较的是两个变量的值是否相等,对于引用型变量表示的是两个变量在堆中存储的地址是否相同,即栈中的内容是否相同。
*
    equals操作表示的两个变量是否是对同一个对象的引用,即堆中的内容是否相同。   ==比较的是2个对象的地址,而equals比较的是2个对象的内容。 显然,当equals为true时,==不一定为true;

我记得视频里老师说,如果比较的是一份字节码 那就用==。

==可以用于基本类型,和应用类型,当用于基本类型时候,是比较值是否相同;当用于引用类型的时候,是比较对象是否相同。
基本类型里是没有equals方法的equals只比较值(对象中的内容)是否相同(相同返回true)。


作者: 铿锵科技    时间: 2013-2-13 00:49
本帖最后由 铿锵科技 于 2013-2-13 11:31 编辑

/*
Set:无序,不可以重复元素。
        |--HashSet:数据结构是哈希表。线程是非同步的。
                                保证元素唯一性的原理:判断元素的hashCode值是否相同。
                                如果相同,还会继续判断元素的equals方法,是否为true。

        |--TreeSet:可以对Set集合中的元素进行排序。
                                底层数据结构是二叉树。
                                保证元素唯一性的依据:
                                compareTo方法return 0.不相等return 1或-1

                                TreeSet排序的第一种方式:让元素自身具备比较性。
                                元素需要实现Comparable接口,覆盖compareTo方法。
                                也种方式也成为元素的自然顺序,或者叫做默认顺序。

                                TreeSet的第二种排序方式。
                                当元素自身不具备比较性时,或者具备的比较性不是所需要的。
                                这时就需要让集合自身具备比较性。
                                
定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。

当两种排序都存在时,以比较器为主。

定义一个类,实现Comparable 接口,覆盖compare方法。
需求:
往TreeSet集合中存储自定义对象学生。
想按照学生的年龄进行排序。
记住,排序时,当主要条件相同时,一定判断一下次要条件。
*/

class TreeSetDemo
{
        public static void main(String[] args)
        {
                //方法一                //TreeSet ts = new TreeSet();
               
                //方法二:使用泛型创建一个TreeSet类装的是Student类型的并传入一个比较器StuComparator
                TreeSet<Student> ts=new TreeSet<Student>(new StuComparator());
               
                ts.add(new Student("lisi02",22));
                ts.add(new Student("lisi007",20));
                ts.add(new Student("lisi09",19));
                ts.add(new Student("lisi08",19));
                ts.add(new Student("lisi007",20));
                ts.add(new Student("lisi01",40));

                Iterator it = ts.iterator();
                while(it.hasNext())
                {
                        Student stu = (Student)it.next();
                        System.out.println(stu.getName()+"..."+stu.getAge());
                }
        }
}

class StuComparator implements Comparator {
        @Override
        public int compare(Object o1, Object o2) {
                Student stu1 = (Student1) o1;
                Student stu2 = (Student1) o2;
                if (stu1.getAge() >= stu2.getAge()) {
                        if (stu1.getAge() == stu2.getAge())
                                return stu1.getName().compareTo(stu2.getName());
                        return -1;
                }
                return 1;
        }

class Student implements Comparable//该接口强制让学生具备比较性。
{
        private String name;
        private int age;

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

        public int compareTo(Object obj)
        {

                //return 0;
               
                if(!(obj instanceof Student))
                        throw new RuntimeException("不是学生对象");
                Student s = (Student)obj;

                System.out.println(this.name+"....compareto....."+s.name);
                if(this.age>s.age)
                        return 1;
                if(this.age==s.age)
                {
                        return this.name.compareTo(s.name);
                }
                return -1;
        }

        public String getName()
        {
                return name;

        }
        public int getAge()
        {
                return age;
        }
}

作者: 铿锵科技    时间: 2013-2-13 11:48
本帖最后由 铿锵科技 于 2013-2-13 11:59 编辑

接上
这是一个HashSet集合的示例:
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class HashSetDemo {

        /**
         * @param args
         */
        public static void main(String[] args) {
                Set<Student2> hs=new HashSet<Student2>();
                hs.add(new Student2("zhangsan1",10));
                hs.add(new Student2("zhangsan2",10));
                hs.add(new Student2("zhangsan3",10));
                hs.add(new Student2("zhangsan1",10));
                hs.add(new Student2("zhangsan2",10));
               //增加了5次记录,但只存入3个证明了不可以重复元素。
                Iterator<Student2> it=hs.iterator();
                while(it.hasNext()){
                        Student2 stu=it.next();
                        System.out.println("name"+stu.getName()+" age:"+stu.getAge());        
                }
               

        }
}

class Student2 {
        private int age;
        private String name;

        Student2() {

        }

        Student2(String name, int age) {
                this.name = name;
                this.age = age;
        }

        public int getAge() {
                return age;
        }

        public void setAge(int age) {
                this.age = age;
        }

        public String getName() {
                return name;
        }

        public void setName(String name) {
                this.name = name;
        }

        @Override
        public int hashCode() {
                return 1;
        }

        @Override
        public boolean equals(Object obj) {
               if(!(obj instanceof Student2))//判断是不是学生
                        throw new RuntimeException("不是学生对象");
                Student2 stu = (Student2) obj;
                if (this.age == stu.age) {//如果是进行比较
                        if (this.name == stu.name) {
                                return true;
                        }
                }
                return false;
        }
}






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