Logo

郎哥编程

TreeSet类

2019-12-27 225

TreeSet类也是一个有序的集合,TreeSet使用二叉树的原理对加入的元素按照升序或降序排序,该类对新添加的元素都会进行排序,将元素插入到二叉树指定的位置。

TreeSet在实现Set接口基础上,增加了一些用于集合的操作方法,增加的主要方法如下。

● E  first ()

返回当前TreeSet集合的第一个元素,E指Element(元素的英文名称简写)。

● E  last()

返回TreeSet集合的最后一个元素。

● SortedSet<E>  headSet (E toElement)

返回一个新的已排序的TreeSet集合,该集合的元素小于toElement元素。

● SortedSet<E>  subSet (E fromElement, E toElement)

返回一个新的已排序的集合,该集合元素范围从fromElement(包含)到toElement(不包含)。

● SortedSet<E>  tailSet (E fromElement, E toElement)

返回一个新的已排序的集合,该集合中元素大于或等于fromElement。

● Comparator<? super E>  comparator()

返回当前TreeSet集合的排序比较器,如果此集合使用其元素的自然排序,则返回null。

案例1:建立TreeSetTest测试类,添加String对象到TreeSet集合。

在set包下新建TreeSetTest测试类。代码如下:

package set;
 
import java.util.TreeSet;
 
/** 
* @ClassName: TreeSetTest 
* @Description: 集合框架(TreeSet类)案例1
* @author 编程训练营 
* @date 
* 
*/
 
public class TreeSetTest {
 
    /**
     * @Title: main
     * @Description: Java程序入口main方法
     * @param args 参数
     *
     * @return void 返回类型 @throws
     */
 
    public static void main(String[] args) {
      
       TreeSet<Integer> set = new TreeSet<Integer>();
       set.add(9);
       set.add(-2);
       set.add(3);
       set.add(10);
       System.out.println(set);
       // 输出集合中第一个元素
       System.out.println("set.first() = " + set.first());
       // 输出集合中最后一个元素
       System.out.println("set.last() = " + set.last());
       // 返回小于4的子集,不包含4
       System.out.println("set.headSet() = " + set.headSet(4));
       // 返回大于5的子集,包含5
       System.out.println("set.tailSet() = " + set.tailSet(5));
       // 返回大于等于-3,小于4的子集
       System.out.println("set.subSet() = " + set.subSet(-3, 4));
 
    }
 
}

与HashSet集合采用通过hash算法来决定元素的存储位置不同,TreeSet采用二叉树的数据结构来存储集合元素。

程序执行结果如下图所示:

 image.png                                            

从输出结果可以看出,TreeSet对加入元素默认按照升序进行排序。

TreeSet的排序原理

TreeSet调用对象元素的compareTo方法来比较元素之间的大小关系,然后将元素按升序或降序排列,因此待加入的元素必须实现compareTo方法,并通过compareTo方法比较两个元素内容的大小。

待加入的元素如何实现compareTo方法呢?Java提供了一个Comparable接口,该接口定义了一个compareTo(Object o)方法,用于比较两个元素的大小,并返回一个整数值。需要加入TreeSet集合的元素必须要实现该接口,该接口的实现代码用于比较当前元素与传入元素的大小进行比较,并返回结果。因此实现该接口类的对象就可以比较大小。当一个对象调用该方法与另一个对象进行比较时,该方法就可以返回比较结果。例如:tempObj1.compareTo(obj2),如果该方法返回0,则代表这两个对象相等;如果该方法返回1,则表明tempObj1大于obj2;如果该方法返回-1,则表明tempObj1小于obj2。

需要加入TreeSet集合的元素必须实现Comparable接口,如果试图把没有实现Comparable接口的类对象加入TreeSet时,程序就会抛出异常。

案例2:建立MyNumber 类,MyNumber没有实现Comparable接口,将MyNumber对象加入TreeSet集合。

在set包下新建MyNumber类。代码如下:

package set;
 
/**
 * @ClassName: MyNumber
 * @Description: 集合框架(TreeSet类)案例2
 * @author 编程训练营
 * @date
 *
 */
 
public class MyNumber {
    public int num;
 
    public MyNumber(int innum) {
       num = innum;
    }
 
    public void OutNum() {
       System.out.println("序号:" + num);
    }
 
}

MyNumber为自定义的序号类,该类没有实现Comparable接口。

在set包下新建TreeSetTest1类,添加MyNumber对象到TreeSet集合。代码如下:

package set;
 
import java.util.TreeSet;
 
/** 
* @ClassName: TreeSetTest1 
* @Description: 集合框架(TreeSet类)案例2
* @author 编程训练营 
* @date 
* 
*/
 
public class TreeSetTest1 {
 
    /**
     * @Title: main
     * @Description: Java程序入口main方法
     * @param @param args 参数
     *
     * @return void 返回类型 @throws
     */
 
    public static void main(String[] args) {
 
       TreeSet<MyNumber> set = new TreeSet<MyNumber>();
       set.add(new MyNumber(12));
       set.add(new MyNumber(8));
       set.add(new MyNumber(19));
 
    }
 
}

程序在TreeSetTest1类的main方法中声明了TreeSet集合,并添加MyNumber对象。运行上述代码后,程序抛出错误,如下图所示:

image.png

从输出结果可以看出,程序抛出“Exception in thread "main" java.lang.ClassCastException: treesetnum.MyNumber cannot be cast to java.lang.Comparable”异常,意思是MyNumber类没有实现Comparable接口,导致进行元素比较时发生错误。

在上面的案例代码中,TreeSet集合添加了三个MyNumber对象,添加第一个对象时,TreeSet里没有任何元素,所以不会出现任何问题,当添加第二个MyNumber对象时,TreeSet就会调用该对象的compareTo(Object obj)方法与集合中的其他元素进行比较,如果其对应的类没有实现Comparable 接口,则会引发ClassCastException异常。

案例3:建立MyNumber1 类,实现Comparable接口,将MyNumber1对象加入TreeSet集合。

在set包下新建MyNumber1类。代码如下:

package set;
 
/**
 * @ClassName: MyNumber1
 * @Description: 集合框架(TreeSet类)案例2
 * @author 编程训练营
 * @date
 *
 */
 
public class MyNumber1 implements Comparable{
    public int num;
 
    public MyNumber1(int innum) {
       num = innum;
    }
 
    public void OutNum() {
       System.out.println("序号:" + num);
    }
 
    @Override
    public int compareTo(Object obj) {
       // TODO Auto-generated method stub
       MyNumber1 inMyNumner = (MyNumber1) obj;
       // 大于返回1
       if (this.num > inMyNumner.getNum())
           return 1;
       // 小于返回-1
       if (this.num < inMyNumner.getNum())
           return -1;
       // 相等返回0
       return 0;
    }
 
    public int getNum() {
       return num;
    }
 
    public void setNum(int num) {
       this.num = num;
    }
 
}

MyNumber1类实现了Comparable接口,在compareTo()方法内对传入的MyNumber1和当前对象的num值进行了比较。如果当前num大于传入的num,该方法返回1;如果当前num小于传入的num,该方法返回-1;若相等则返回0。

在set包下新建TreeSetTest2类,添加MyNumber1对象到TreeSet集合。代码如下:

package set;
 
import java.util.Iterator;
import java.util.TreeSet;
 
/** 
* @ClassName: TreeSetTest2 
* @Description: 集合框架(TreeSet类)案例3
* @author 编程训练营 
* @date 
* 
*/
 
public class TreeSetTest2 {
 
    /**
     * @Title: main
     * @Description: Java程序入口main方法
     * @param @param args 参数
     *
     * @return void 返回类型 @throws
     */
 
    public static void main(String[] args) {
      
       TreeSet<MyNumber1> set = new TreeSet<MyNumber1>();
       set.add(new MyNumber1(12));
       set.add(new MyNumber1(8));
       set.add(new MyNumber1(19));
 
       // 输出集合元素
       Iterator<MyNumber1> iteror = set.iterator();
       while (iteror.hasNext()) {
           MyNumber1 temp = iteror.next();
           temp.OutNum();
 
       }
 
    }
 
}

程序执行结果如下图所示:

image.png

从图中可以看出,修改后的代码可以正常地加入元素,并能对加入的元素进行正确排序。

在实际编程中,需要注意的是放入TreeSet集合中的元素必须是可“排序”的,对加入的元素(自定义类),若要实现compareTo方法,必须实现Comparable接口。在Java  SDK中,已经有一些实现了Comparable接口的类,其中包括String字符串类,还包括Float、Interger、Long、Short、Double等数字类。

代码在线纠错(通义千问 qwen-max)

支持粘贴多个代码文件,提交后由阿里云通义千问自动分析代码漏洞、语法错误、逻辑问题并给出修改建议。
您已解锁 AI 代码纠错功能,可正常使用!

评论区

登录 后发表评论
暂无评论