set和TreeSet的使用和原理


   假如有个项目,要把一个公司的员工的名字,年龄,工资做一个表单,然后可以实现点按钮就按姓名笔画或者拼音,按工资水平,按年龄或者按其他方式进行排列,当然用数据库是最好的,但是如果要求用集合呢,个人认为TreeSet是个可以考虑的类,

set的特点:

不包含重复元素

                                    Set集合没有索引(即没有顺序)

 TreeSet的特点:

底层数据结构红黑树(red-black-tree)

                                      存储到红黑树中的对象,会进行排序

                                      线程不安全集合,运行速度快

引入一个set案例:

/*

 * Set集合存储并迭代

 * Set集合代码,List集合代码,是一样的,但是set有自己的特点

 * 不接受重复的元素,输出元素自然排序

 */

import java.util.*;

 

public class SetDemo {

    public static void main(String[] args) {

       method_2();      

    }

    /*

     * Set集合存储自定义对象Person,并迭代

     * 将姓名和年龄,相同的对象去掉

     */

    public static void method_2(){

       Set<Person> set = newHashSet<Person>();     

       set.add(new Person("c2",182));

       set.add(new Person("d4",184));

       set.add(new Person("a2",182));

       set.add(new Person("d4",183));

       set.add(new Person("c2",182));

      

/*

       输出:输出没有顺序,不会像treeSet那样自然排序

       Person [name=a2, age=182]

       //有重复的被砍掉了,如果字符相同,比较数字,这主要是调用了

//person类中自带的compareTo(Person p)方法

       Person [name=d4, age=184]

       Person [name=d4, age=183]

       Person [name=c2, age=182]

*/

             

       Iterator<Person> it = set.iterator();

       while(it.hasNext()){

           System.out.println(it.next());

       }

    }

}

 

程序里引用了一个类Person泛型,Person是一个标准类实现了Comparable<Person>接口,这里将person类简单写下:

package bokebao;

public class Person implements Comparable<Person> {

    . . . . . .

    @Override返回了String字符串

    public String toString() {

       return"Person[name=" +name +", age=" +age +"]";

    }

    //重写了hashCode()方法

    public int hashCode(){

       returnname.hashCode()+age*31;

    }

//重写了equals(Object obj)方法

    public boolean equals(Object obj){

       if(obj==null)

           return false;

       if(this==obj)

           return false;

       if(objinstanceof Person){

           Person p=(Person)obj;

           return this.name.equals(p.name)&&this.age==p.age;

       }

       return false;

    }

    @Override重写了compareTo(Person p)方法

    public int compareTo(Person p) {

       // TODO Auto-generatedmethod stub

       int number=this.name.compareTo(p.name);

       //三目运算符,如果姓名相同,比较年龄按照年龄进行顺序输出,

       return number==0?this.age-p.age:number;

   

    }

}

 

为什么在类中要加这么多重写还要实现接口呢?

这就是TreeSet使用类作为泛型的一个重点和难点,也是很多小伙伴困扰的地方,我们再调一个TreeSet案例看一下:

/*

 * TreeSet集合存储对象并迭代

 */

import java.util.*;

 

public class TreeSetDemo {

    public static void main(String[] args) {

       method_2();      

       method_1();

    }

    /*

     *TreeSet存储自定义对象Person,并迭代

     * 排序是要使用比较器对象,不使用对象的自然顺序

     * 比较器优先级最高

     */

    public static void method_2(){

       //TreeSet构造方法中,传递写好的,比较器对象

       Set<Person> set = new TreeSet<Person>(new CompareDemo());

       //java.util 接口 Comparator<T>

 

       set.add(new Person("zhangsan",18));

       set.add(new Person("lisi",20));

       set.add(new Person("wangwu",19));

       set.add(new Person("zhaoliu",17));

       for(Person p : set){

           System.out.println(p);

       }  

    }

   

    /*

     *TreeSet存储自定义对象Person,并迭代

     * 排序使用的是对象的自然顺序

     */

    public static void method_1(){

       Set<Person> set = new TreeSet<Person>();

       set.add(new Person("zhangsan",18));

       set.add(new Person("wisi",20));

       set.add(new Person("vangwu",19));

       set.add(new Person("uhaoliu",17));

       for(Person p : set){

           System.out.println(p);

       }

    }

   

}

 

这个案例调用了两个方法,方法1没什么好说的,还是调用了Person类的重写的hashCode()和equals(Object obj)方法,如果类返回的字符串的哈希值相同,就用equals(Objectobj)比较字母或数字,注意几个方面

1、       Person必须实现接口Comparable否则在TreeSet中它会报错,类作为泛型

对象,必须重写接口中调用的方法,否则,TreeSet方法中默认的自然排序没办法排列,类里面不重写无法实现自然排序,这点一定要注意,你会发现程序写完了,Eclipse也没有报编译错误,就是运行出错。

2、       TreeSet要实现自然顺序排序,必然要调用内部的comparator()方法,comparator()指定者是通过接口SortedSet<E> 中的抽象方法comparator

返回的一个是一个抽象的接口,要实现这个接口就只有在Person类中实现,所以在类中实现了java。Lang下的接口Comparable,这样Person就可以直接调用compareTo方法了,而主方法,也可以将调用的接口实例化

    为了应付不同的要求排序方式我们还可以重写Comparator接口,这样就实现了TreeSet的快速存取的排序

 

/*

 * 自定义的比较器对象

 *   实现Comparator接口

 */

 

public class CompareDemoimplements java.util.Comparator<Person>{

    /*

     * p1和p2对象的年龄,年龄相同,在比较姓名

     * 注意:p1对象的age-p2对象的age

     * 比较器中,不允许直接使用Person类的私有成员,必须依靠get set

     */

    public int compare(Person p1, Person p2) {

       //计算两个对象的年龄差

       int age = p1.getAge() - p2.getAge();

       return age==0? p1.getName().compareTo(p2.getName()) :age;

    }

     

}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值