TreeSet总结

  • TreeSet是依靠TreeMap来实现的,底层结构是“二叉树的数据结构。
  • TreeSet是一个有序集合,TreeSet中的元素将按照升序排列,缺省是按照自然排序进行排列,所有要存入到TreeSet中的集合元素必须首先具备可比较性,其类必须要实现“Compareble”接口的“compareTo()方法”。
  • 如果元素不具备比较性,或者想按照自定义的方法去排序,也可以自定义的比较器,此时要实现“Comparetor接口中的”compare()方法。
  • 我们可以在构造TreeSet对象时,传递实现Comparator接口的比较器对象。(TreeSet(Comparator<? super E> comparator) 构造一个新的空 TreeSet,它根据指定比较器进行排序。)
int compareTo(T o):o是要比较的对象,此方法返回的是一个int型,比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。值为”0,1,-1“。
import java.util.*;

public class TreeSetTest {
    public static void main(String[] args) {
        Set ts = new TreeSet();
        ts.add(new Teacher("zhangsan", 1));
       // ts.add(new String("lisi"));
        ts.add(new Teacher("wangmazi", 3));
        ts.add(new Teacher("mazi", 3));
        ts.add(new Teacher("mazi", 0));
        ts.add(new Teacher("mazi", 2));
        Iterator it = ts.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
    }
}


class Teacher implements Comparable {
    private int num;
    private String name;
    
    Teacher(){
    }
    
    Teacher(String name, int num){
        this.num = num;
        this.name = name;
    }
    
    public void setNum(int num){
        this.num = num;
    }
    public int getNum(){
        return num;
    }
    
    public void setName(String name){
        this.name = name;
    }
    public String getName(){
        return name;
    }

    public String toString() {
        return "老师" + this.num  + ": "+ "姓名: " + this.name;
    }

    public int compareTo(Object o) {
    if(!(o instanceof Teacher)){
    System.out.println("----------");
        throw new RuntimeException("二者不具备比较性");
    }
        //为安全起见,将要比较的对象强制转换成Teacher对象再进行比较:
        Teacher ss = (Teacher) o;
        //此处的规则是按照学号进行默认的自然排序,根据compareTo()方法的返回值看当前的对象的num和要比较的num
        //的大小关系来确定他的存放位置。        
        int result = num > ss.num ? 1 : (num == ss.num ? 0 : -1);
        //如果二个num相等,在主要条件不满足的情况下要比较次要条件,即,比较name的关系,因为name 是String类型。而String类实现了
        //Comparable接口,则比较name中的字母顺序即可(如果在num相等的情况下不比较name的关系,则按照Set接口的规定就认为是同一个
        //集合元素,则以后num相等的不Teacher对象就不会被存进集合,这显然合常理了:
        if (result == 0) {
            //此处调用String的compareTo()方法进行name的比较:
            result = name.compareTo(ss.name);
        }
        return result;
    }
}
View Code
调用compareTo()比较数值型的二个值大于时,一个简单的方法是用基本数据类型的包装类中实现的compareTo()方法,如:
public int compareTo(Integer anotherInteger)如果该 Integer 等于 Integer 参数,则返回 0 值;如果该 Integer 在数字上小于 Integer 参数,则返回小于 0 的值;如果 Integer 在数字上大于 Integer 参数,则返回大于 0 的值(有符号的比较)。  

  int result = new Integer(this.num).compareTo(new Integer(ss.num));
  if(result==0){
  result = this.name.compareTo(ss.name);
}
return result;

构造一个可接收自定义比较器的TreeSet:

public TreeSet(Comparator<? super E> comparator) {
this(new TreeMap<E,Object>(comparator));
}

1.定义一个比较器类,该比较器类必须实现Comparator接口中的compare()方法:

    class MyComparator implements Comparator{}

2.创建TreeSet集合时,传入一个自定义好的比较器对象:

    TreeSet ts = new TreeSet(new MyComparator ());

import java.util.*;

public class TreeSetTest1 {
    public static void main(String[] args) {
    //构建TreeSet时传入一个自定义的比较器:
        TreeSet ts = new TreeSet(new Teacher.TeacherCompare());
        ts.add(new Teacher("zhangsan", 2));
        ts.add(new Teacher("lisi", 1));
        ts.add(new Teacher("wangmazi", 3));
        ts.add(new Teacher("mazi", 3));
        Iterator it = ts.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
    }
}

class Teacher {
    private int num;
    private String name;

    Teacher(String name, int num) {
        this.num = num;
        this.name = name;
    }

    public String toString() {
        return "学号:" + num + "    姓名:" + name;
    }

    static class TeacherCompare implements Comparator {// 老师自带的一个比较器

        public int compare(Object o1, Object o2) {
        if(!(o1 instanceof Teacher) || !(o2 instanceof Teacher)){
            throw new RuntimeException("不具备比较性");
        }
            Teacher s1 = (Teacher) o1;// 转型之后进行比较
            Teacher s2 = (Teacher) o2;// 转型
            int result = s1.num > s2.num ? 1 : (s1.num == s2.num ? 0 : -1);
            if (result == 0) {
                result = s1.name.compareTo(s2.name);
            }
            return result;
        }

    }
}
View Code

 对二叉树的理解:

给定的一个基准元素,要与之比较的元素若是大于基准元素则放在基准元素的右边,反之放在左边。依次类推:

如,对于一个存到二叉树结构的容器中的一个元素20,现要将[10,30,9,11,32,29]也存入其中,则要对后存入的元素与20进行比较,最终的二叉树结构如下图所示:(每次新加入的元素都首先与20进行比较,大于20的放在其右,如果其右已经有其它元素,则再跟这些元素比较,也是按照大于放右,小于放左的规则。而按照自然排序,最终取出的结果顺序是按红字标出的顺序)

对于TreeSet这种二叉树结构的集合来说,存放元素依靠compareTo()或者compare(),默认是自然排序,跟存入的顺序不一定相同。若是想用TreeSet来实现存取的顺序相同该怎么做呢? 其实理解了二叉树的结构就不难实现了,如果让所有的后存入的元素都位于第一个元素的右侧,也就是说存入时就强制其由小到大存入,结构如下:

怎么实现这种存入呢?只需compareTo()方法的返回值永远为一个正数即可,比如1:

public int compareTo(){

  return 1;

}

这样的话,后来存入的元素要调用compareTo()去比较时,永远比前一个大。

posted @ 2015-11-23 23:16  心灵召唤  阅读(364)  评论(0)    收藏  举报