java中的Comparator和Comparable比较器+单例模式

 java中的Comparator和Comparable比较器的用法

Comparable和Comparator都是用来实现集合中的排序的,Comparator位于包java.util下,而Comparable位于包java.lang下,Comparable是一个对象本身就已经支持自比较所需要实现的接口(如 String、Integer 自己就可以完成比较大小操作),是内部定义的排序;而后者在一个独立的类中实现比较,是外部实现的排序。 如果一个类没有实现Comparable接口,或是这个对象不支持自比较或者自比较函数不能满足你的要求时,可以通过Comparator来实现比较算法进行排序,并且为了使用不同的排序标准做准备,比如:升序、降序。所以,如想实现排序,就需要让类对象自身实现Comparable接口,重写其中的compareTo(T o)方法;或在外部定义比较器实现Comparator接口,重写其compare(T o1,T o2)方法。前者只有一个参数,后者有两个参数。排序时可以调用java.util.Arrays.sort()来排序对象数组,或是调用集合中的sort()方法就可以按照相应的排序方法进行排序。方法返回一个基本类型的整型,返回负数表示o1小于o2,返回0表示o1和o2相等,返回正数表示o1大于o2。

Comparator 是策略模式(strategy design pattern),就是不改变对象自身,而用一个策略对象(strategy object)来改变它的行为。比如:你想对整数采用绝对值大小来排序,Integer 是不符合要求的,你不需要去修改 Integer 类(实际上你也不能这么做)去改变它的排序行为,只要使用一个实现了Comparator接口的对象来实现控制它的排序就行了。

例子:

import java.util.Arrays;
import java.util.Comparator;

class Person implements Comparable<Person>{   private String name;   private int age;   public Person(String name, int age) {     this.name = name;     this.age = age;   }   public String getName() {     return this.name;   }   public int getAge() {     return this.age;   }   @Override   public String toString() {     return ""+this.name+" "+this.age;   }   @Override   public int compareTo(Person o) {     if (this.getName().compareTo(o.getName()) != 0)       return this.getName().compareTo(o.getName());     else if (this.getAge() < o.getAge())         return -1;     else if (this.getAge() > o.getAge())         return 1;     else return 0;     }   } } class Cmp implements Comparator {   @Override   public int compare(Object arg0, Object arg1) {     Person a = (Person) arg0;     Person b = (Person) arg1;     if (a.getName().compareTo(b.getName()) != 0)       return a.getName().compareTo(b.getName());     else if (a.getAge() < b.getAge())       return -1;     else if (a.getAge() > b.getAge())       return 1;     else return 0;     }   } } public class Main {   public static void main(String[] args) {     Person[] p = new Person[4];     p[0] = new Person("ZZZ",19);     p[1] = new Person("AAA", 109);     p[2] = new Person("AAA", 19);     p[3] = new Person("YYY",100);     // Arrays.sort(p);//调用自有的排序     Arrays.sort(p, new Cmp());//调用Comparator定义的排序     System.out.println(Arrays.toString(p));   } }

2.对复合数据类型的数据的排序

  函数原型: (1)public static<T> void sort(T[] a,Comparator c) 根据指定比较器产生的顺序对指定对象数组进行排序。

        (2)public static<T> void sort(T[] a,int fromIndex,int toIndex,Comparator c) 根据指定比较器产生的顺序对指定对象数组的指定范围进行排序。 

  说明:这个两个排序算法是“经过调优的合并排序”算法。

  代码实例:

import java.util.Arrays;

import java.util.Arrays;
import java.util.Comparator;

class Point{
  int x;
  int y;
}
 //比较器,x坐标从小到大排序;x相同时,按照y从小到大排序
class MyComprator implements Comparator {
  public int compare(Object arg0, Object arg1) {
    Point t1=(Point)arg0;
    Point t2=(Point)arg1;
    if(t1.x != t2.x)
      return t1.x>t2.x? 1:-1;
    else
      return t1.y>t2.y? 1:-1;
    }
  }
  public class Arraysort {
    Point[] arr;
    Arraysort(){
    arr=new Point[4]; //定义对象数组arr,并分配存储的空间
    for(int i=0;i<4;i++)
    arr[i]=new Point();
  }
  public static void main(String[] args) {
    Arraysort sort=new Arraysort();
    sort.arr[0].y=1; //初始化,对象数组中的数据
    sort.arr[0].x=2;
    sort.arr[1].x=2;
    sort.arr[1].y=2;
    sort.arr[2].x=1;
    sort.arr[2].y=2;
    sort.arr[3].x=0;
    sort.arr[3].y=1;
    Arrays.sort(sort.arr, new MyComprator()); //使用指定的排序器,进行排序
    for(int i=0;i<4;i++) //输出排序结果
      System.out.println("("+sort.arr[i].x+","+sort.arr[i].y+")");
  }
}

执行输出:

 

单例模式的实现的两种方式,如下所示:
1、懒汉式,线程不安全

是否 Lazy 初始化:是
是否多线程安全:否
实现难度:易
描述:这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。
这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作。

代码实例:

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
  
    public static Singleton getInstance() {  
      if (instance == null) {  
          instance = new Singleton();  
      }  
      return instance;  
    }  
}  

  


2、懒汉式,线程安全
是否 Lazy 初始化:是
是否多线程安全:是
实现难度:易
描述:这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。
优点:第一次调用才初始化,避免内存浪费。
缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。
getInstance() 的性能对应用程序不是很关键(该方法使用不太频繁)。

代码实例:

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
    public static synchronized Singleton getInstance() {  
      if (instance == null) {  
          instance = new Singleton();  
      }  
      return instance;  
    }  
} 

  


3、饿汉式
是否 Lazy 初始化:否
是否多线程安全:是
实现难度:易
描述:这种方式比较常用,但容易产生垃圾对象。
优点:没有加锁,执行效率会提高。
缺点:类加载时就初始化,浪费内存。
它基于 classloder 机制避免了多线程的同步问题,不过,instance 在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用 getInstance 方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化 instance 显然没有达到 lazy loading 的效果。

代码实例:

public class Singleton {  
    private static Singleton instance = new Singleton();  
    private Singleton (){}  
    public static Singleton getInstance() {  
      return instance;  
    }  
}  

 

原文地址:https://www.cnblogs.com/lxy151/p/8400260.html