A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 朝花夕拾 中级黑马   /  2012-11-25 15:00  /  1251 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 张雄 于 2012-11-25 22:20 编辑

HashSet保证元素的唯一性时,复写了equals方法,而TreeSet是根据Comparable接口的compareTo方法或者Comparator接口的compare方法的返回值是否为0,来确定是否添加元素,本人这块有些没有懂,求详细解释!!!

评分

参与人数 1技术分 +1 收起 理由
崔政 + 1 淡定

查看全部评分

3 个回复

正序浏览
HashSet保证元素的唯一性:HashSet存储元素时存储的其实是元素的哈希值,默认的每个对象的哈希值是不一样的,这样元素就可以添加到集合中。HashSet实现元素的唯一性是在添加元素(add)时实现的,查看"add"的源码,可以知道add方法底层依赖于HashCode和equals两个方法, 并且,它先走HashCode方法,当其值相等时再走equals方法。
HashSet保证元素唯一性思路:让创建的元素哈希值一样,然后根据自己的需求重写equals的比较方式,当equals返回true的时候,说明集合中有相同属性的元素,这个时候,集合就不存储数据。当equals方法false的时候,就直接把元素添加到集合中。
代码体现:
        //重写HashCode和equals方法
        public boolean equals(Object obj) {
                System.out.println(this+"###"+obj);
                //提高效率,让元素的哈希值一样
                if(this==obj){
                        //返回值是true进行equals判断
                        return true;
                }
                //提高程序的健壮性
                if(!(obj instanceof Person)){
                        return false;
                }
                //Object类向下转型
                Person p = (Person)obj;
                return this.name.equals(p.name) && this.num == p.num;
        }
        public int hashCode() {
                //同下的不比较方法,下面的更加简化便捷
                return this.name.hashCode()+this.num*18;
TreeSet保证元素的唯一性:根据Comparable接口的compareTo的方法或者Comparator接口的compare的方法的返回值是否为0来确定是否是重复元素。如果是0,就不添加元素。
TreeSet保证元素唯一性的思路:1、让元素本身具备比较性(Comparable接口的compareTo的方法);这个方法是在对象里面进行比较,但是这种方案,如果需求不断变化,那么就会导致代码需要经常改变,这是不合理不方便的。
2、让集合具备比较性(Comparator接口的compare的方法);这个方法集合中的元素可以没有比较性,相对于“1”中的方法合理一些。
代码体现:       
        TreeSet<Teacher> ts = new TreeSet<Teacher>(new Comparator<Teacher>() {
                        public int compare(Teacher t1, Teacher t2) {
                                int num = t1.getAge() - t2.getAge();
                                // 当num一样(age),还要比较姓名
                                int num2 = (num == 0) ? t1.getName().compareTo(t2.getName()): num;
                                return num2;
                        }
                });
回复 使用道具 举报
HashSet底层的数据结构是哈希表,哈希表是存放了一堆哈希值的一张表,存的顺序是按照哈希值存的,在存入时要先判断哈希值,如果哈希值一样了,再判断是否是同一对象,所以HashSet为了保证元素的一致性,要通过两个方法来完成即:hashCode()和equals(),hashCode()方法来判断元素的哈希值是否相同,如果相同,再通过equals()方法判断是否是同一个对象,如果元素的哈希值不同,就不会调用equals()方法,我们使用基本数据类型或系统中提供的引用类型作为元素放到HashSet时.在使用添加,删除,判断时,人家已经都复写好了,所以我们只是拿来用,但是如果是我们自己定义了一个类,要把这个类产生的对象,放到HaseSet中并要使用集合中的一些方法时,就要在自定义的类中覆写hashCode()方法和equals()方法,使我们自定义的类也具有可以比较功能;
对于TreeSet集合,你在往里存入数据时,该集合就会对里面的元素进行排序,它是以ASCII码表进行排序的,从此可见,只有那些可以用ASCII表来表示的元素可以不用写比较的方法,直接添加到TreeSet集合中,只要是我们自定义的类,都要覆写比较的方法,这样在使用TreeSet集合存入元素时,它才知道怎么存放,所以一定要实现Comparable接口覆写compareTo()方法或继承Comparator类覆写compare()方法
总之,为了方法使用,我们一般在定义一个类时,都要覆写hashCode()方法和equals()和实现Comparable接口覆写compareTo()方法或继承Comparator类覆写compare()方法,不管这个类的对象以后是否会使用到集合

评分

参与人数 1技术分 +1 收起 理由
古银平 + 1 神马都是浮云

查看全部评分

回复 使用道具 举报
Treeset对元素进行排序的方式一:
让元素自身具备比较功能,就需要实现comparable接口,覆盖comparaTo( )方法。如果不要按照对象中具备的自然顺序进行排序
如果对象中不具备自然顺序,怎么办?

那就使用treeset集合第二种排序方式二(自定义比较器):
让集合自身具备比较功能,定义一个类实现comparator接口,覆盖compareTo方法。将该类对象作为参数传递给treeset集合的构造函数。
import java.util.*;
public class TreeSetDemo {
        public static void main(String[] args) {
                TreeSet<Student> t = new TreeSet<Student>();
                t.add(new Student("lisi1",12));
                t.add(new Student("lisi2",10));
                t.add(new Student("lisi3",11));
                t.add(new Student("wangwu",11));
               
                Iterator<Student> it = t.iterator();
                while(it.hasNext()){
                        Student stu = it.next();
                        System.out.println(stu.getName()+"::"+stu.getAge());
                }
        }
}

class Student implements Comparable{
        private String name;
        private int age;
        Student(String name,int age){
                this.name=name;
                this.age=age;
        }
        public String getName() {
                return name;
        }
        public void setName(String name) {
                this.name = name;
        }
        public int getAge() {
                return age;
        }
        public void setAge(int age) {
                this.age = age;
        }
        public int compareTo(Object obj) {
                if(!(obj instanceof Student))
                        throw new RuntimeException("不是学生类");
                Student s = (Student)obj;
                if(this.age>s.age)
                        return 1;
                if(this.age==s.age){
                        return this.name.compareTo(s.name);
                }
                return -1;       
        }
}

评分

参与人数 1技术分 +1 收起 理由
崔政 + 1 淡定

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马