黑马程序员-JAVA学习之Comparable与Comparator接口

--------android培训java培训、期待与你交流!--------

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());
        }
    }
}

//

测试代码运行结果是:

添加了7个元素,工号是乱的,并且有两个工号重复,最后得出的结果是,重复工号的两个元素没有添加成功,其它元素按工号排序,

--------------------------------------------------------------------------------------------------------------------------

下面是使用比较器进行排序的代码

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());
    }

}

//

结果是:

也可以在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接口的,但是我们又想要对元素进行排序,而且写匿名类的方法也挺方便的.

时间: 2024-08-29 06:38:30

黑马程序员-JAVA学习之Comparable与Comparator接口的相关文章

黑马程序员——JAVA学习笔记四(继承、接口、内部类)

1,    通过extends关键字让类与类之间产生继承关系.多个类中存在相同属性和行为时,将这些内容抽取到单独的一个类中,那么多个类无需定义这些属性和行为,只要继承那个类即可,已存在的类叫做超类,基类,或父类.新类称为子类,派生类,孩子类. 子类可以直接访问父类中的非私有的属性和行为.子类无法继承父类中私有的内容.JAVA不支持多继承,只支持单继承,多实现. 继承提高了代码复用性,让类与类之间产生了关系.为多态提供了前提. 2,    super关键字代表父类中成员变量内存空间的标示.两个作用

黑马程序员-JAVA学习日记-数组YNPB

黑马程序员学习笔记黑马程序员编程基础数组培训.培训.期待与您交流!数组:是存储同一种数据类型的的集合,也叫容器:特点:是数组中每个元素都有索引从开始:数组的定义式:数据类型数组名数据类型元素个数:数据类型数组名数据类型元素个数:如:数据类型数组名数据类型元素数据类型数组名元素如:如果元素确定就用这一种:数组中有一个属性:获取数组中的元素个数,即数组的长度:中的内存机制:栈:存储局部变量,一般定义在函数内的变量成为局部变量:特点:当内存中数据操作完成后,所占空间会自动释放栈内存堆:是通过创建的实体

黑马程序员——JAVA学习笔记十(IO)

1,    可以从其中读入一个字节序列的对象成为输入流,可以向其中写入一个字节序列的对象就做输出流.这些字节序列的来源地可以是文件,也可以是网络连接或者内存块.抽象类InputStream和OutputStream构成了I/O层次的基础.因为字节流不便于处理以Unicode存储的信息,所以有了Writer和Reader抽象类,这些从其中继承的类都是读入和写入基于2个字节的Unicode码元,而不是单个字节.   2,    InputStream 与OutputStream: abstract

黑马程序员——JAVA学习笔记十四(高新技术三)

10 代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供定的服务. 按照代理的创建时期,代理类可以分为两种. 静态代理:由程序员创建或特定工具自动生成源代码,再对其编译.在程序运行前,代理类的.class文件就已经存在了. 动态代

黑马程序员——JAVA学习笔记五(异常)

1,     异常:是在运行时期发生的不正常情况. 在java中用类的形式对不正常情况进行了描述和封装对象.描述不正常的情况的类,就称为异常类. 以前正常流程代码和问题处理代码相结合,现在将正常流程代码和问题处理代码分离,提高阅读性. 其实异常就是java通过面向对象的思想将问题封装成了对象,用异常类对其进行描述. 不同的问题用不同的类进行具体的描述.比如角标越界.空指针异常等等. 问题很多,意味着描述的类也很多,将其共性进行向上抽取,形成了异常体系. 不正常情况分成了两大类: Throwabl

黑马程序员——JAVA学习笔记八(集合)

1,    JAVA最初版本只为最常用的数据结构提供了很少的一组类:Vector.Stack.Hashtable.BitSet与Enumeration接口,从JAVA1.2版本开始推出了一组功能完善的的数据结构. 集合类的由来:  对象用于封装特有数据,对象多了需要存储,如果对象的个数不确定.  就使用集合容器进行存储. 集合特点: 1,用于存储对象的容器. 2,集合的长度是可变的. 3,集合中不可以存储基本数据类型值. 4,接口与实现相互分离. 集合框架是为表示和操作集合而规定的一种统一的标准

黑马程序员——java学习9(毕15-16总结)——TreeSet

1. 1 package learn; 2 /* 3 * |--TreeSet 4 * 可以对Set集合排序 5 * 底层数据结构是二叉树 6 * 保证数据唯一性的依据:compareTo方法return 0:原序return 1: 7 * 8 * TreeSet排序的第一种方式:让元素子集具备比较性.元素需要实现compareTo接口,覆盖compareTo方法 9 * 也称为元素的自然顺序,默认顺序 10 * 11 * TreeSet的第二种排序方式:当元素自身不具备比较性时,或者具备的比较

黑马程序员--java基础------继承,抽象,接口

-----------android培训.java培训.java学习型技术博客.期待与您交流!------------  继承 一.概述         继承是面向对象的一个重要特征.当多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继那个类即可.这时,多个类可以称为子类,单独的这个类称为父类或者超类. 这样类与类之间就存在了继承的关系.子类可以直接访问父类中的非私有的属性和行为.在代码中通过extends关键字表示继承关系.例: class

黑马程序员-JAVA学习之银行业务调度系统分析与实现

--------android培训.java培训.期待与你交流!-------- 银行业务调度系统 模拟实现银行业务调度系统逻辑,具体需求如下:1 银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口.2 有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费.电话费之类业务的客户).3 异步随机生成各种类型的客户,生成各类型用户的概率比例为:VIP客户 :普通客户 :快速客户 = 1 :6 :3.4 客户办理业务所需时间有最大值和最小值,在该