java集合之TreeSet的整理

TreeSet与HashSet的区别

TreeSet和HashSet相同的地方,就是集合里面不允许有重复的元素。 存储方面,HashSet存储时是乱序存储的,而TreeSet是按照自己定义的顺序,底层通过二叉树来实现存储的,所以,TreeSet中的元素要实现Comparable接口。或者有一个自定义的比较器。我们可以在构造TreeSet对象时,传递实现Comparator接口的比较器对象。

TreeSet的主要性质

1、TreeSet中不能有重复的元素;

2、TreeSet具有排序功能;

3、TreeSet中的元素必须实现Comparable接口并重写compareTo()方法,TreeSet判断元素是否重复 、以及确定元素的顺序 靠的都是这个方法;(这条性质比较重要,如果读者对TreeSet内部机制比较熟悉的话这条性质应该不难理解;如果读者不太理解的话可以参看以下这篇文章http://wlh269.iteye.com/blog/376430 )

4、对于java类库中定义的类,TreeSet可以直接对其进行存储,如String,Integer等(因为这些类已经实现了Comparable接口);

5.而对于自定义类,就必须在自定义类中实现Comparable接口,或者传递实现Comparator接口的比较对象,不然的话,程序是不知道按照怎么样的顺序来存储自定义类的对象。

Comparable接口的实现和使用

实现方法:
int compareTo(T o)
比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。

强烈推荐 (x.compareTo(y)==0) == (x.equals(y)) 这种做法,但不是 严格要求这样做。一般来说,任何实现 Comparable 接口和违背此条件的类都应该清楚地指出这一事实。推荐如此阐述:“注意:此类具有与 equals 不一致的自然排序。”

参数:
o - 要比较的对象。
返回:
负整数、零或正整数,根据此对象是小于、等于还是大于指定对象。
抛出:
ClassCastException - 如果指定对象的类型不允许它与此对象进行比较。


实例:

public class Person implements Comparable<Person> {
    private String name;
    private int age;
    public Person() {
        super();

    }
    public Person(String name, int age) {
        super();
        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;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
    /*@Override
    public boolean equals(Object obj) {
        System.out.println("执行了吗");
        Person p = (Person)obj;
        return this.name.equals(p.name) && this.age == p.age;
    }
    @Override
    public int hashCode() {
        final int NUM = 38;
        return name.hashCode() * NUM + age;
    }*/
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)                        //调用的对象和传入的对象是同一个对象
            return true;                        //直接返回true
        if (obj == null)                        //传入的对象为null
            return false;                       //返回false
        if (getClass() != obj.getClass())       //判断两个对象对应的字节码文件是否是同一个字节码
            return false;                       //如果不是直接返回false
        Person other = (Person) obj;            //向下转型
        if (age != other.age)                   //调用对象的年龄不等于传入对象的年龄
            return false;                       //返回false
        if (name == null) {                     //调用对象的姓名为null
            if (other.name != null)             //传入对象的姓名不为null
                return false;                   //返回false
        } else if (!name.equals(other.name))    //调用对象的姓名不等于传入对象的姓名
            return false;                       //返回false
        return true;                            //返回true
    }
    public int compareTo(Person o) {
        int length = this.name.length() - o.name.length();              //比较长度为主要条件
        int num = length == 0 ? this.name.compareTo(o.name) : length;   //比较内容为次要条件
        return num == 0 ? this.age - o.age : num;                       //比较年龄为次要条件
    }

}

与Comparator的区别

Comparator位于包java.util下,而Comparable位于包java.lang下,Comparable接口将比较代码嵌入自身类中,而后者在一个独立的类中实现比较。 如果类的设计师没有考虑到Compare的问题而没有实现Comparable接口,可以通过 Comparator来实现比较算法进行排序,并且为了使用不同的排序标准做准备,比如:升序、降序。

public class Person implements Comparable<Person> {
    private String name;
    private int age;
    public Person() {
        super();

    }
    public Person(String name, int age) {
        super();
        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;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)                        //调用的对象和传入的对象是同一个对象
            return true;                        //直接返回true
        if (obj == null)                        //传入的对象为null
            return false;                       //返回false
        if (getClass() != obj.getClass())       //判断两个对象对应的字节码文件是否是同一个字节码
            return false;                       //如果不是直接返回false
        Person other = (Person) obj;            //向下转型
        if (age != other.age)                   //调用对象的年龄不等于传入对象的年龄
            return false;                       //返回false
        if (name == null) {                     //调用对象的姓名为null
            if (other.name != null)             //传入对象的姓名不为null
                return false;                   //返回false
        } else if (!name.equals(other.name))    //调用对象的姓名不等于传入对象的姓名
            return false;                       //返回false
        return true;                            //返回true
    }
    /*@Override
    //按照年龄排序
    public int compareTo(Person o) {
        int num = this.age - o.age;             //年龄是比较的主要条件
        return num == 0 ? this.name.compareTo(o.name) : num;//姓名是比较的次要条件
    }*/
    /*@Override
    //按照姓名排序
    public int compareTo(Person o) {
        int num = this.name.compareTo(o.name);      //姓名是主要条件
        return num == 0 ? this.age - o.age : num;   //年龄是次要条件
    }*/
    public int compareTo(Person o) {
        int length = this.name.length() - o.name.length();              //比较长度为主要条件
        int num = length == 0 ? this.name.compareTo(o.name) : length;   //比较内容为次要条件
        return num == 0 ? this.age - o.age : num;                       //比较年龄为次要条件
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值