欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java中TreeSet使用注意

程序员文章站 2022-04-17 11:20:37
...

1、我们知道在集合中,如果需要保持集合中的元素有序,则可以使用TreeSet集合。

 

2、TreeSet判断元素重复的方法和HashSet一样,但同时它还会保持集合中元素处于有序状态。

 

3、如果直接使用TreeSet的默认无参构造函数,则其工作起来会像使用sort()方法一样使用其中元素的compareTo()方法进行排序,所以此时其中的元素必须实现Comparable接口,并覆盖其中的CompareTo()方法(定义对象的比较规则)。

    实例一:

package com.linwei;

import java.util.TreeSet;

public class TestTreeSetString {
	public static void main(String[] args) {
		new TestTreeSetString().go();
	}
	
	public void go(){
        //String已实现Comparable接口,所以TreeSet使用String类覆写的compareTo()方法进行大小比较
		TreeSet<String> tree =new TreeSet<String>();
		tree.add("b");
		tree.add("c");
		tree.add("g");
		tree.add("e");
		tree.add("a");
		tree.add("f");
		
		System.out.println(tree);
	}
}

执行输出:[a, b, c, e, f, g]

  

    由于String类已经实现了Comparable接口,所以在TreeSet中可以直接使用,但如果是自定义的类,则必须自己实现Comparable接口,并覆盖compareTo()方法,编写自定义的比较规则。

 

    再看下以下实例二:

package com.linwei;

import java.util.TreeSet;

public class TestTreeSet {
	public static void main(String[] args) {
		new TestTreeSet().go();
	}
	
	public void go(){
		Book b1=new Book("How");
		Book b2=new Book("Remix");
		Book b3=new Book("Finding");
		
		TreeSet<Book> tree =new TreeSet<Book>();
		tree.add(b1);
		tree.add(b2);
		tree.add(b3);
		
		System.out.println(tree);
	}
	
	class Book {
		String title;
		
		public Book(String t){
			this.title=t;
		}
		public String getTitle() {
			return title;
		}
		public void setTitle(String title) {
			this.title = title;
		}
		
		@Override
		public String toString() {
			return "Book [title=" + title + "]";
		}
	}
}

   

    问题一:以上程序代码能否通过编译?

    答:能。

 

    问题二:以上程序能否顺利执行?最终的执行结果是什么?

    答:不能。

 

    执行结果:Exception in thread "main" java.lang.ClassCastException: com.linwei.TestTreeSet$Book cannot be cast to java.lang.Comparable。

    结果说明:很明显,异常是说Book对象不能转换为Comparable接口类型。

    解决方法:修改Book类,实现Comparable接口,并覆盖其compareto()方法。

 

    修改后代码如下实例二(修正):

package com.linwei;
import java.util.TreeSet;
public class TestTreeSet {
	public static void main(String[] args) {
		new TestTreeSet().go();
	}

	public void go(){
		Book b1=new Book("How");
		Book b2=new Book("Remix");
		Book b3=new Book("Finding");
		
		TreeSet<Book> tree =new TreeSet<Book>();
		tree.add(b1);
		tree.add(b2);
		tree.add(b3);
		
		System.out.println(tree);
	}
	
	class Book implements Comparable<Book>{
		String title;
		
		public Book(String t){
			this.title=t;
		}
		public String getTitle() {
			return title;
		}
		public void setTitle(String title) {
			this.title = title;
		}
		
		@Override
		public int compareTo(Book b) {
			return getTitle().compareTo(b.getTitle());
		}
		@Override
		public String toString() {
			return "Book [title=" + title + "]";
		}
	}
}

执行结果:[Book [title=Finding], Book [title=How], Book [title=Remix]]

  

4、如果使用TreeSet带Comparator类型参数的构造函数,则必须另外单独创建一个专门的比较器对象(实现Comparator接口,并覆盖其中的compare()方法)。

    实例三:

 

package com.linwei;

import java.util.Comparator;
import java.util.TreeSet;

public class TestTreeSet2 {
	
	public static void main(String[] args) {
		new TestTreeSet2().go();
	}
	
	public void go(){
		Book b1=new Book("How");
		Book b2=new Book("Remix");
		Book b3=new Book("Finding");
		
		//需传入一个Comparator类型的比较器对象
		TreeSet<Book> tree =new TreeSet<Book>(new BookComparator());
		tree.add(b1);
		tree.add(b2);
		tree.add(b3);
		
		System.out.println(tree);
	}
	
	class Book {
		String title;
		
		public Book(String t){
			this.title=t;
		}
		public String getTitle() {
			return title;
		}
		public void setTitle(String title) {
			this.title = title;
		}
		
		@Override
		public String toString() {
			return "Book [title=" + title + "]";
		}
	}
	
	class BookComparator implements Comparator<Book>{
		@Override
		//覆写compare()方法,根据书名进行大小比较
		public int compare(Book b1, Book b2) {
			return b1.getTitle().compareTo(b2.getTitle());
		}
		
	}
}

执行结果:[Book [title=Finding], Book [title=How], Book [title=Remix]]