java常用类库续3(比较器Comparable、Comparator、观察者设计模式、正则表达式、定时调度)

比较器(Comparable、Comparator)

Comparable接口

可以直接使用java.util.Arrays类进行数组的排序操作,但对象所在的类必须实现Comparable接口,用于指定排序接口。

Comparable接口定义如下:

[java]  view plain copy print ?
  1. public interface Comparable<T>{  
  2.    public int compareTo(T o);  
  3. }  

从接口的定义格式上来看,可以发现如果想实现对象属性的排序功能,要实现Comparable接口,并且覆写compareTo(T o)方法。此方法返回的是一个int类型的数据,但是此int类型的数据只能是一下三种:

·1:表示大于

·-1:表示小于

·0:表示等于

看如下的实例:一个学生类,里面有三个属性姓名、年龄、成绩三个属性,要求按成绩由高到底排序,如果成绩相等,则按照年龄由底到高排序。

[java]  view plain copy print ?
  1. class Student implements Comparable<Student>  //指定类型为Student  
  2. {  
  3.     private String name;  
  4.     private int age;  
  5.     private float score;  
  6.     public Student(String name,int age,float score){  
  7.         this.name=name;  
  8.         this.age=age;  
  9.         this.score=score;  
  10.     }  
  11.     public String toString(){  
  12.         return name+"\t\t"+age+"\t\t"+score+"\t\t";  
  13.     }  
  14.     public int compareTo(Student stu){  //覆写compareTo方法,实现排序规则的应用  
  15.         if(this.score<stu.score){  
  16.             return -1;  
  17.         }  
  18.         if(this.score>stu.score){  
  19.             return 1;  
  20.         }  
  21.         else{  
  22.             if(this.age<stu.age){  
  23.                 return -1;  
  24.             }  
  25.             if(this.age>stu.age){  
  26.                 return 1;  
  27.             }  
  28.             else{  
  29.                 return 0;  
  30.             }  
  31.         }  
  32.     }  
  33. }  
  34. public class ComparableDemo01  
  35. {  
  36.     public static void main(String args[]){  
  37.         Student stu[]={  
  38.             new Student("张三",20,89.1f),  
  39.             new Student("李四",26,53.5f),  
  40.             new Student("王五",30,79.0f),  
  41.             new Student("赵六",20,66.0f),  
  42.             new Student("孙七",25,66.0f)  
  43.         };  
  44.         java.util.Arrays.sort(stu); //进行排序操作  
  45.         for(Student x:stu){ //循环输出  
  46.             System.out.println(x);  
  47.         }  
  48.     }  
  49. }  

注意:如果在此时Student类没有实现Comparable接口,则在执行的时候会出现一下异常:

[java]  view plain copy print ?
  1. Exception in thread "main" java.lang.ClassCastException: Student cannot be cast  
  2. to java.lang.Comparable  

另一种比较器Comparator

此比较器其实跟Comparable是非常类似的。如果现在已经完成了一个类的开发,但是并没有实现Comparable接口,此时肯定是无法进行对象排序操作的,所以为了解决这种问题,java又定义了另一个比较器的操作接口---Comparator。此接口在java.util包中,接口如下定义:

[java]  view plain copy print ?
  1. pubic interface Comparator<T>{  
  2.   public int compare(T o1,T o2);  
  3.   boolena equals(Object obj);  
  4. }  

代码如下:

[java]  view plain copy print ?
  1. import java.util.*;  
  2. class Student    {  
  3.     private String name;  
  4.     private int age;  
  5.     private float score;  
  6.     public Student(String name,int age,float score){  
  7.         this.name=name;  
  8.         this.age=age;  
  9.         this.score=score;  
  10.     }  
  11.     public void setName(String name){  
  12.         this.name=name;  
  13.     }  
  14.     public String getName(){  
  15.         return name;  
  16.     }  
  17.     public void setAge(int age){  
  18.         this.age=age;  
  19.     }  
  20.     public int getAge(){  
  21.         return age;  
  22.     }  
  23.     public String toString(){  
  24.         return name+"\t\t"+age+"\t\t"+score+"\t\t";  
  25.     }  
  26. }  
  27. class StudentComparator implements Comparator<Student>  
  28. {  
  29.     //因为Object类中已经覆写过equals方法  
  30.     public int compare(Student s1,Student s2){  
  31.         if(s1.equals(s2)){  
  32.             return 0;  
  33.         }     
  34.         else if(s1.getAge()<s2.getAge()){    //按照年龄进行比较  
  35.             return 1;  
  36.         }  
  37.         else{  
  38.             return -1;  
  39.         }  
  40.     }  
  41. }  
  42. public class ComparableDemo02  
  43. {  
  44.     public static void main(String args[]){  
  45.         Student stu[]={  
  46.             new Student("张三",20,89.1f),  
  47.             new Student("李四",26,53.5f),  
  48.             new Student("王五",30,79.0f),  
  49.             new Student("赵六",20,66.0f),  
  50.             new Student("孙七",25,66.0f)  
  51.         };  
  52.         java.util.Arrays.sort(stu,new StudentComparator()); //进行排序操作  
  53.         for(Student x:stu){ //循环输出  
  54.             System.out.println(x);  
  55.         }  
  56.     }  
  57. }  

总结:在开发中尽量还是使用Comparable在需要排序的类上实现好此接口,而Comparator需要单独建立一个排序的类,这样如果有很多的话,则排序的规则类也就会很多,操作起来比较麻烦些。注意:在java中只要是对象排序,永远都是以Comparable接口为准的。

观察者设计模式

具体内容

所谓观察者设计模式,就是某一样东西被多个观察者观察,当这样东西发生变化,则会及时反馈到每个观察者的身上。如果要想实现观察者设计模式,则必须依靠java.util包中的Observable类和Observer接口。

例子:现在很多的购房者都在关注着房子的变化,每当房子价格变化的时候,所有的观察者都能够立即观察到

[java]  view plain copy print ?
  1. import java.util.* ;  
  2. class House extends Observable{ // 表示房子可以被观察  
  3.     private float price ;// 价钱  
  4.     public House(float price){  
  5.         this.price = price ;  
  6.     }  
  7.     public float getPrice(){  
  8.         return this.price ;  
  9.     }  
  10.     public void setPrice(float price){  
  11.         // 每一次修改的时候都应该引起观察者的注意  
  12.         super.setChanged() ;    // 设置变化点  
  13.         super.notifyObservers(price) ;// 价格被改变  
  14.         this.price = price ;  
  15.     }  
  16.     public String toString(){  
  17.         return "房子价格为:" + this.price ;  
  18.     }  
  19. };   
  20. class HousePriceObserver implements Observer{  
  21.     private String name ;  
  22.     public HousePriceObserver(String name){ // 设置每一个购房者的名字  
  23.         this.name = name ;  
  24.     }  
  25.     public void update(Observable o,Object arg){  
  26.         if(arg instanceof Float){  
  27.             System.out.print(this.name + "观察到价格更改为:") ;  
  28.             System.out.println(((Float)arg).floatValue()) ;  
  29.         }  
  30.     }  
  31. };  
  32. public class ObserDemo01{  
  33.     public static void main(String args[]){  
  34.         House h = new House(1000000) ;  
  35.         HousePriceObserver hpo1 = new HousePriceObserver("购房者A") ;  
  36.         HousePriceObserver hpo2 = new HousePriceObserver("购房者B") ;  
  37.         HousePriceObserver hpo3 = new HousePriceObserver("购房者C") ;  
  38.         h.addObserver(hpo1) ;  
  39.         h.addObserver(hpo2) ;  
  40.         h.addObserver(hpo3) ;  
  41.         System.out.println(h) ; // 输出房子价格  
  42.         h.setPrice(666666) ;    // 修改房子价格  
  43.         System.out.println(h) ; // 输出房子价格  
  44.     }  
  45. };  

正则表达式

正则表达式可以方便的对数据进行匹配,可以执行更加复杂的字符串验证、拆分、替换等功能。

例如:现在要求判断一个字符串是否由数字组成,有以下两种方式:

·不使用正则完成

·使用正则完成

第一种方式代码:

[java]  view plain copy print ?
  1. public class RegexDemo01{  
  2.     public static void main(String args[]){  
  3.         String str = "1234567890" ;     // 此字符串由数字组成  
  4.         boolean flag = true ;           // 定义一个标记变量  
  5.         // 要先将字符串拆分成字符数组,之后依次判断  
  6.         char c[] = str.toCharArray() ;  // 将字符串变为字符数组  
  7.         for(int i=0;i<c.length;i++){ // 循环依次判断  
  8.             if(c[i]<'0'||c[i]>'9'){       // 如果满足条件,则表示不是数字  
  9.                 flag = false ;          // 做个标记  
  10.                 break ;                 // 程序不再向下继续执行  
  11.             }  
  12.         }  
  13.         if(flag){  
  14.             System.out.println("是由数字组成!") ;  
  15.         }else{  
  16.             System.out.println("不是由数字组成!") ;  
  17.         }  
  18.     }  
  19. };  

第二中方式代码:

[java]  view plain copy print ?
  1. import java.util.regex.Pattern ;  
  2. public class RegexDemo02{  
  3.     public static void main(String args[]){  
  4.         String str = "1234567890" ;     // 此字符串由数字组成  
  5.         if(Pattern.compile("[0-9]+").matcher(str).matches()){   // 使用正则  
  6.             System.out.println("是由数字组成!") ;  
  7.         }else{  
  8.             System.out.println("不是由数字组成!") ;  
  9.         }  
  10.     }  
  11. };  

Pattern、Matcher类

这两个类为正则的核心操作类,都是定义在java.util.regex包中。Pattern类主要是进行正则规范(如之前的操作“[0-9]“就属于正则规范)的编写,而Matcher类主要是执行规范,验证一个字符串是否符合规范。

常用正则规则:


·\d:表示数字, [0-9]

·\D:表示非数字,[^0-9]

·\w:表示字母、数字、下划线,[a-zA-Z0-9]

·\W:[^a-zA-Z0-9]

常用正则规范2:


以上的正则,如果要想驱动起来,则必须依靠Pattern和Matcher类。

Pattern主要是表示一个规则的意思,即:正则表达式的规则需要在Pattern类中使用。

Matcher类主要表示使用Pattern指定好的规则验证。

Pattern类的常用方法:

方法

描述

public static Pattern compile(String regex)

指定正则表达式规则

public Matcher matcher(CharSequence input)

返回Mather类的实例

public String[] split(CharSequence input)

字符串拆分

在Patter类中如果要想取得Pattern类的实例,则必须调用compile()方法。

本类中没有明确的构造方法可以使用,那么此类的构造方法肯定被私有化了,如果是这样的类,都可以通过本类中的一个静态方法获得该类的实例。

Matcher类中的常用方法:

方法

描述

Public Boolean matches()

执行验证

Public String replaceAll(String replacement)

字符串替换

实例操作:(验证日期是否合法)

[java]  view plain copy print ?
  1. import java.util.regex.Pattern ;  
  2. import java.util.regex.Matcher ;  
  3. public class RegexDemo03{  
  4.     public static void main(String args[]){  
  5.         String str = "1983-07-27" ;     // 指定好一个日期格式的字符串  
  6.         String pat = "\\d{4}-\\d{2}-\\d{2}" ;   // 指定好正则表达式  
  7.         Pattern p = Pattern.compile(pat) ;  // 实例化Pattern类  
  8.         Matcher m = p.matcher(str) ;    // 实例化Matcher类  
  9.         if(m.matches()){        // 进行验证的匹配,使用正则  
  10.             System.out.println("日期格式合法!") ;  
  11.         }else{  
  12.             System.out.println("日期格式不合法!") ;  
  13.         }  
  14.     }  
  15. };  

在Pattern类中也可以使用正则进行字符的拆分功能:

[java]  view plain copy print ?
  1. import java.util.regex.Pattern ;  
  2. import java.util.regex.Matcher ;  
  3. public class RegexDemo04{  
  4.     public static void main(String args[]){  
  5.         // 要求将里面的字符取出,也就是说按照数字拆分  
  6.         String str = "A1B22C333D4444E55555F" ;  // 指定好一个字符串  
  7.         String pat = "\\d+" ;   // 指定好正则表达式  
  8.         Pattern p = Pattern.compile(pat) ;  // 实例化Pattern类  
  9.         String s[] = p.split(str) ; // 执行拆分操作  
  10.         for(int x=0;x<s.length;x++){  
  11.             System.out.print(s[x] + "\t") ;  
  12.         }  
  13.     }  
  14. };  

还可以使用Matcher类中的字符串替换功能:

[java]  view plain copy print ?
  1. import java.util.regex.Pattern ;  
  2. import java.util.regex.Matcher ;  
  3. public class RegexDemo05{  
  4.     public static void main(String args[]){  
  5.         // 要求将里面的字符取出,也就是说按照数字拆分  
  6.         String str = "A1B22C333D4444E55555F" ;  // 指定好一个字符串  
  7.         String pat = "\\d+" ;   // 指定好正则表达式  
  8.         Pattern p = Pattern.compile(pat) ;  // 实例化Pattern类  
  9.         Matcher m = p.matcher(str) ;    // 实例化Matcher类的对象  
  10.         String newString = m.replaceAll("_") ;  
  11.         System.out.println(newString) ;  
  12.     }  
  13. };  

String类对正则的支持

在String类中有以下三个方法是支持正则操作的:

方法

描述

public boolean matches(String regex)

字符串匹配

public String replaceAll(String regex,String replacement)

字符串替换

public String[] split(String regex)

字符串拆分

代码如下:

[java]  view plain copy print ?
  1. import java.util.regex.Pattern ;  
  2. import java.util.regex.Matcher ;  
  3. public class RegexDemo06{  
  4.     public static void main(String args[]){  
  5.         String str1 = "A1B22C333D4444E55555F".replaceAll("\\d+","_") ;  
  6.         boolean temp = "1983-07-27".matches("\\d{4}-\\d{2}-\\d{2}") ;  
  7.         String s[] = "A1B22C333D4444E55555F".split("\\d+") ;  
  8.         System.out.println("字符串替换操作:" + str1) ;  
  9.         System.out.println("字符串验证:" + temp) ;  
  10.         System.out.print("字符串的拆分:") ;  
  11.         for(int x=0;x<s.length;x++){  
  12.             System.out.print(s[x] + "\t") ;  
  13.         }  
  14.     }  
  15. };  

但是,使用正则需要注意一点,看如下的代码:

[java]  view plain copy print ?
  1. import java.util.regex.Pattern ;  
  2. import java.util.regex.Matcher ;  
  3. public class RegexDemo07{  
  4.     public static void main(String args[]){  
  5.         String info = "LXH:98|MLDN:90|LI:100" ;         // 定义一个字符串  
  6.         // 拆分的形式:  
  7.         /* 
  8.             LXH -->  98 
  9.             MLDN    -->  90 
  10.             LI  -->  100 
  11.         */  
  12.         String s[] = info.split("\\|") ;  
  13.         System.out.println("字符串的拆分:") ;  
  14.         for(int x=0;x<s.length;x++){  
  15.             String s2[] = s[x].split(":") ;  
  16.             System.out.println(s2[0] + "\t" + s2[1]) ;  
  17.         }  
  18.     }  
  19. };  

如果有时候发现一个字符串无法按照指定的字符拆分的话,则需要使用“\”转义,转义的时候连个“\”表示一个“\”。

总结:

1、  使用正则可以方便完成字符串的验证、拆分、替换等功能。

2、  在开发中一般会使用String类提供好的正则支持,很少使用Pattern或者是Matcher类。

3、  在使用一些正则的时候,对于一些敏感的字符要进行转义。

定时调度

定时调度:每隔一段时间,程序会自动执行,成为定时调度。

如果要使用定时调度,则必须保证程序运行这才可以,也就说是相当于定时调度在程序之外又启动了一个新的线程。使用Timer和TimerTask两个类完成定时调度。

Timer类

Timer类是一种线程设施,可以用来实现在某一个时间或某一段时间后,安排某一个任务执行一次,或定期重复执行。该功能要与TimerTask类配合使用。TimerTask类用来实现由Timer安排的一次或重复执行的某一个任务。

Timer类的常用方法:

方法

类型

描述

public Timer()

构造

用来创建一个计时器并启动

 

public void cancel()

普通

 

用来终止该计时器,并放弃所有已安排的任务,对当前正在执行的任务没有影响。

public int purge()

普通

将所有已经取消的任务移除,一般用来释放内存空间

public void schedule(TimerTask task,Date time)

普通

 

安排一个任务在指定的时间执行,如果已经超过该时间,则立即执行。

public void scheduleAtFixedRate(TimerTask task,Date firstTime,long period)

普通

安排一个任务在指定的时间执行,之后以近似固定的频率(单位:毫秒)重复执行

Schedule()与scheduleAtFixedRate()方法的区别:

两者的区别在于重复执行任务时,对于时间间隔出现延迟的情况处理:

·Schedule()方法的执行时间间隔永远是固定的,如果之前出现了延迟的情况,之后也会按照设定好的间隔时间执行。

·scheduleAtFixedRate()方法可以根据出现的延迟时间自动调整下一次间隔的执行时间。

TimerTask类

要想执行具体的任务,则必须使用TimerTask类。TimerTask是一个抽象类,如果要使用该类,需要建立一个子类继承该类,并实现其中的抽象方法。

方法

描述

 

public void cancle()

 

用来终止此任务,如果该任务只执行一次并且还没有执行,则永远不会再执行,如果为重复执行任务,则之后不会再执行(如果该任务正在执行,则执行完后不会再执行)

public void run()

该任务所要执行的具体操作,该方法为引入接口Runable中的方法,子类需要覆写。

 

public long scheduledExecutionTime()

 

返回最近一次执行任务的时间(如果正在运行,则返回该任务的执行安排时间),一般在run()方法中调用,用来判断当前是否有足够的时间来执行完该任务。

代码示例:定时调度的程序,每隔2秒打印一次。

[java]  view plain copy print ?
  1. //完成具体的任务操作  
  2. import java.util.*;  
  3. import java.text.SimpleDateFormat;  
  4. class MyTask extends TimerTask  //任务调度类都要继承TimerTask  
  5. {  
  6.     public void run(){  
  7.         SimpleDateFormat sd=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");  
  8.         System.out.println("当前系统时间为:"+sd.format(new Date()));  
  9.     }  
  10. }  

完成的是一个具体的任务操作类,以后定时调度就是调度此类的操作,方法的主体就是run()方法。注意要继承TimerTask类,下面建立测试类,并执行任务调度:

[java]  view plain copy print ?
  1. import java.util.*;  
  2. public class TestTask  
  3. {  
  4.     public static void main(String args[]){  
  5.         Timer t=new Timer();  
  6.         MyTask mytask=new MyTask();  
  7.         t.schedule(mytask,1000,2000);  
  8.     }  
  9. }  

总结:一般在web开发中此内容比较有用,因为要维护一个容器不关闭才可以一直定时调度下去。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值