public interface Comparator<T>
此接口提供对某个collection集合对象进行强行整体排序的比较函数。可以将 Comparator 传递给 sort() 方法(如 Collections.sort 或 Arrays.sort),从而允许在排序顺序上实现自定义精确控制。还可以使用 Comparator 来控制某些数据结构(如有序 set或有序映射)的顺序,或者为那些没有自然顺序的collection集合对象提供排序。
public interface Comparable<T>
此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。这些元素组成的有序对象列表的顺序就叫做自然顺序。实现此接口的对象列表(和数组)可以通过 Collections.sort(和 Arrays.sort)进行自动排序。实现此接口的对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。
public class TreeSet<E>extends AbstractSet<E>implements NavigableSet<E>, Cloneable, Serializable
Set接口中的元素是无序的(说无序是因为添加和顺序和元素取出的顺序是不一致的),但是TreeSet里面的元素是相对有序的,可以按照某种要求对集合中的元素进行排序,使用元素的自然顺序对元素进行排序要求实现Comparable接口,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。此实现为基本操作(add、remove 和 contains)提供受保证的 log(n) 时间开销。即对Set集合的添加,删除,检查是否包含操作都会调用自然比较或比较器的比较方法.
TreeSet有两种实现排序的方式:
(1). 让元素本身具有比较性,即集合中的元素每个都能和另一个元素进行比较,
元素本身要实现Comparable接口并实现里面的compareTo方法以保证元素本身具有比较性,
int compareTo(T o)比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。
(2). 让容器自身具有比较性,即集合主动来对集合中的每个元素进行排序,
当元素本身不具有比较性或者具备的比较性不是所需要的,就在TreeSet建立实例的时候,传入Comparator接口的实现子类的实例。这个Comparator子类必须实现compare方法。
int compare(T o1,T o2)比较用来排序的两个参数。根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数。
在TreeSet集合添加元素的时候,如果要添加的元素的类型没有实现Comparable的话,而又没有在Set初始化的时候指定Comparator时,在运行的时候会出现类型转换出错"java.lang.ClassCastException"的异常,所以我们要为这个集合中元素的类型实现Comparable接口,即为这个类型添加一个自然排序方法.
但是有些时候我们不想在实体类中实现Comparable接口的话,或者有些实体类不方便修改的时候,再或者我们对这些类提供的自然排序方法不满意的时候,我们就可以使用Comparator接口了,然后在TreeSet初始化时选择可以提供比较器的构造函数
TreeSet(Comparator<? super E> comparator)
构造一个新的空 TreeSet,它根据指定比较器进行排序。
这时可以定义一个实现了Comparator接口的类,或者直接使用一个匿名类来对Set集合中的元素进行排序.
这里我们定义一个员工类,这个员工类实现了Comparable接口,提供了自然排序方法,是按工号排序的,如果工号重复,则元素不添加,因为Set集合的元素是唯一的.
// 员工类,实现Comparable接口,如果没有实现的话,直接在Set集合中添加这个类型的元素会出现类型转换出错的异常
class Employee implements Comparable
{
// 如果没有实现这个接口方法时,Set集合添加元素时会出错
@Override
public int compareTo(Object arg0)
{
// TODO Auto-generated method stub
Employee e = (Employee) arg0;
return this.number.compareTo(e.getNumber());
}
// 姓名
private String name;
// 工号
private String number;
public Employee(String _name, String _number)
{
this.name = _name;
this.number = _number;
}
// 以下为对应的get.set方法
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getNumber()
{
return number;
}
public void setNumber(String number)
{
this.number = number;
}
}
在使用自然排序的时候.
import java.util.*;
public class Test1
{
public static void main(String[] args)
{
// TODO Auto-generated method stub
Set set = new TreeSet();
set.add(new Employee("王五", "03"));
set.add(new Employee("赵六", "04"));
set.add(new Employee("张三", "01"));
set.add(new Employee("李四", "02"));
set.add(new Employee("田七", "05"));
set.add(new Employee("赵六1", "04"));
set.add(new Employee("田七1", "05"));
for (Object s : set)
{
Employee e = (Employee) s;
System.out.println(e.getName() + ":" + e.getNumber());
}
}
}
class Employee implements Comparable
{
// 如果没有实现这个接口方法时,Set集合添加元素时会出错
@Override
public int compareTo(Object arg0)
{
// TODO Auto-generated method stub
Employee e = (Employee) arg0;
return this.number.compareTo(e.getNumber());
}
// 姓名
private String name;
// 工号
private String number;
public Employee(String _name, String _number)
{
this.name = _name;
this.number = _number;
}
// 以下为对应的get.set方法
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getNumber()
{
return number;
}
public void setNumber(String number)
{
this.number = number;
}
}
在使用自然排序的时候.
import java.util.*;
public class Test1
{
public static void main(String[] args)
{
// TODO Auto-generated method stub
Set set = new TreeSet();
set.add(new Employee("王五", "03"));
set.add(new Employee("赵六", "04"));
set.add(new Employee("张三", "01"));
set.add(new Employee("李四", "02"));
set.add(new Employee("田七", "05"));
set.add(new Employee("赵六1", "04"));
set.add(new Employee("田七1", "05"));
for (Object s : set)
{
Employee e = (Employee) s;
System.out.println(e.getName() + ":" + e.getNumber());
}
}
}
//
测试代码运行结果是:
添加了7个元素,工号是乱的,并且有两个工号重复,最后得出的结果是,重复工号的两个元素没有添加成功,其它元素按工号排序,
import java.util.*;
public class Test1
{
public static void main(String[] args)
{
// TODO Auto-generated method stub
Set set = new TreeSet(new Comparator()
{
public int compare(Object arg0, Object arg1)//直接在初始化方法中使用匿名类来实现比较器功能
{
Employee e1 = (Employee) arg0;
Employee e2 = (Employee) arg1;
return e1.getName().compareTo(e2.getName());
}
});
set.add(new Employee("王五", "03"));
set.add(new Employee("赵六", "04"));
set.add(new Employee("张三", "01"));
set.add(new Employee("李四", "02"));
set.add(new Employee("田七", "05"));
set.add(new Employee("赵六1", "04"));
set.add(new Employee("田七1", "05"));
set.add(new Employee("田七", "005"));
for (Object s : set)
{
Employee e = (Employee) s;
System.out.println(e.getName() + ":" + e.getNumber());
}
}
}
--------------------------------------------------------------------------------------------------------------------------
下面是使用比较器进行排序的代码
import java.util.*;
public class Test1
{
public static void main(String[] args)
{
// TODO Auto-generated method stub
Set set = new TreeSet(new MyComparator());
set.add(new Employee("王五", "03"));
set.add(new Employee("赵六", "04"));
set.add(new Employee("张三", "01"));
set.add(new Employee("李四", "02"));
set.add(new Employee("田七", "05"));
set.add(new Employee("赵六1", "04"));
set.add(new Employee("田七1", "05"));
set.add(new Employee("田七", "005"));
for (Object s : set)
{
Employee e = (Employee) s;
System.out.println(e.getName() + ":" + e.getNumber());
}
}
}
class MyComparator implements Comparator
{
@Override
public int compare(Object arg0, Object arg1)
{
Employee e1 = (Employee) arg0;
Employee e2 = (Employee) arg1;
return e1.getName().compareTo(e2.getName());
}
}
public class Test1
{
public static void main(String[] args)
{
// TODO Auto-generated method stub
Set set = new TreeSet(new MyComparator());
set.add(new Employee("王五", "03"));
set.add(new Employee("赵六", "04"));
set.add(new Employee("张三", "01"));
set.add(new Employee("李四", "02"));
set.add(new Employee("田七", "05"));
set.add(new Employee("赵六1", "04"));
set.add(new Employee("田七1", "05"));
set.add(new Employee("田七", "005"));
for (Object s : set)
{
Employee e = (Employee) s;
System.out.println(e.getName() + ":" + e.getNumber());
}
}
}
class MyComparator implements Comparator
{
@Override
public int compare(Object arg0, Object arg1)
{
Employee e1 = (Employee) arg0;
Employee e2 = (Employee) arg1;
return e1.getName().compareTo(e2.getName());
}
}
//
结果是:
也可以在TreeSet初始化的时候使用匿名类进行排序.
如:
//
import java.util.*;
public class Test1
{
public static void main(String[] args)
{
// TODO Auto-generated method stub
Set set = new TreeSet(new Comparator()
{
public int compare(Object arg0, Object arg1)//直接在初始化方法中使用匿名类来实现比较器功能
{
Employee e1 = (Employee) arg0;
Employee e2 = (Employee) arg1;
return e1.getName().compareTo(e2.getName());
}
});
set.add(new Employee("王五", "03"));
set.add(new Employee("赵六", "04"));
set.add(new Employee("张三", "01"));
set.add(new Employee("李四", "02"));
set.add(new Employee("田七", "05"));
set.add(new Employee("赵六1", "04"));
set.add(new Employee("田七1", "05"));
set.add(new Employee("田七", "005"));
for (Object s : set)
{
Employee e = (Employee) s;
System.out.println(e.getName() + ":" + e.getNumber());
}
}
}
JAVA中的大多数的类型都已经实现了Comparable接口,比如String和Integer,都有compareTo()方法,以上的实例代码中也是直接使用了String类的这个方法来进行比较的,
但是在一般情况下还是推荐使用Comparator接口,因为现在有很多的实例类是没有实现Comparable接口的,但是我们又想要对元素进行排序,而且写匿名类的方法也挺方便的.