zoukankan      html  css  js  c++  java
  • JAVA学习之Comparable与Comparator接口

     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接口的,但是我们又想要对元素进行排序,而且写匿名类的方法也挺方便的.
  • 相关阅读:
    【概念】using 三种使用方式
    2019-7-2 作业1 2 3
    异常
    java.lang.NullPointerException
    课外作业(建立double类型的小数,按照四舍五入保留2位小数)
    作业1.2.3.4
    左自增与右自增的区别
    深入了解JVM(Java虚拟机)
    Eclipse报错Could not resolve archetype
    ThinkPad E550 连蓝牙鼠标logitech M557
  • 原文地址:https://www.cnblogs.com/fylx/p/3985730.html
Copyright © 2011-2022 走看看