Java基础高级
1.正则表达式
什么是正则表达式 通过一定规则将一个非常长的字符串匹配出对应的值,具有自己的特定的语法规则。应用场景 匹配出输出的手机号是否符合规定 , 提取网页中邮箱地址。
1.1普通字符和元字符
在正则表达式中,所有的字符分为两个类 普通字符和元字符
- 主要的元字符有写字母、大写字母、数字、下划线、部分特殊符号、非西文字符等
- 主要元字符:. \ { } * + ? ( ) [ ] - | ^ $
- . 表示任意一个字符(除了换行符)
- \ 转移符,用来改变其他字符的含义,
2.Pattern类
正则表达式中通过什么样的方式来进行匹配的呢。通过这个pattern的类来放入正则表达式再将需要匹配的字符串和正则放到macher中
2.1常用的正则表达式
常用的正则表达式
- 校验数字:^[0-9]*$
- 校验整数或者小数:^[0-9]+([.][0-9]+){0,1}$
- 校验qq号:[1-9][0-9]{4,}
- 校验手机号: ^1[34578]\d{9}$
- 校验身份证:(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|x|X)$)
- 校验日期(格式:yyyy-mm-dd,已考虑平闰年):^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$
- 校验email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
- 校验URL:^[a-zA-z]+://[^\s]*$
简单匹配案列1:
1 package com; 2 import java.util.regex.Matcher; 3 import java.util.regex.Pattern; 4 public class RegexTest2 5 { 6 public static void main(String []args) 7 { 8 String regex="[abc]";//str="a" "b" "c" 表示可以a可以b可以c 9 //helloa|b|c 这样把整个字符串切开了 无法匹配到b和c 10 //写法二 11 String regex2="[^abc]";//匹配除了abc之外任意的一个字符 12 //str =“d” 比如说d啊 f 啊 都都可以的 13 //写法三 14 String regex3="[0-8]"; 15 String regex31="[A-Z]";//字幕a到z的任意一个字母都可以 16 String regex4 ="[0-9a-zA-Z]";//字符类的普通语法 17 //在字符内的元字符 会被自动转义为点字符 18 String regex5="[.]"; 19 String regex6="\\w";//代表一个单词字符 20 String regex7="\\W";//代表一个非单词字符 21 String regex8=""; 22 //String regex8="" 23 // \d 代表数字字符 24 // \D 代表非数字字符,等同于[^0-9] 25 //\s 代表空白字符 26 // \S代表非字符内容 27 //转义字符后面的字符一定要可以被转义才行 28 //[\\] 29 String str="a"; 30 String str2="你"; 31 String str3="10";//10是两个字符 有无法匹配上去 32 String str31="B"; 33 String str5="."; 34 String str6="啊";// 35 String str7=""; 36 String str8="xabxxabmmab"; 37 Pattern pattern = Pattern.compile(regex); 38 Matcher matcher =pattern.matcher(str); 39 //创建一个匹配序列对象 40 boolean fine =matcher.find(); 41 String group =matcher.group();//返回当前和regex匹配的字符串 42 boolean match = Pattern.matches(regex, str); 43 boolean match2 = Pattern.matches(regex2, str2); 44 boolean match3= Pattern.matches(regex2, str2); 45 boolean match5= Pattern.matches(regex5, str5); 46 boolean match6= Pattern.matches(regex6, str6); 47 boolean match7= Pattern.matches(regex7, str6); 48 // ^拖字符 有非得意思 49 // 拖字符和短横线有一些变化 50 // 短横线一定有它自己的链接规则 51 // 52 /* 53 * 在正则里面 54 * 55 */ 56 System.out.println(match); 57 System.out.println(match2); 58 System.out.println(match3); 59 System.out.println(match5); 60 System.out.println(match6); 61 System.out.println(match7); 62 } 63 }
2.2元字符的使用案列
匹配出一个字符串中所有的qq邮箱
1 package com; 2 import java.util.regex.Matcher; 3 import java.util.regex.Pattern; 4 5 public class RegexTest3 6 { 7 public static void main(String []args) 8 { 9 10 // String regex="ab"; 11 String regex2="[1-9][0-9]{4,}@qq.com";//qq邮箱的正则表达式 12 String str="[email protected]@[email protected]"; 13 // 打印出一个字符串所有的qq邮箱 14 Pattern pattern =Pattern.compile(regex2); 15 Matcher matcher =pattern.matcher(str); 16 /* 17 boolean find =matcher.find(); 18 //调用一次find 就去找一次 19 boolean find2 =matcher.find(); 20 */ 21 while(matcher.find()) 22 { 23 String group=matcher.group(); 24 System.out.println(group); 25 } 26 27 /* 28 29 String group = matcher.group(); 30 System.out.println(group); 31 */ 32 } 33 34 }
2.3Macher类
在正则macher类中有许多方法
其中macher.find 表示匹配正则一个子字符串 macher,group 表示正则匹配后的子字符串
贪婪匹配:在重复匹配时,默认会匹配尽可能多的字符
非贪婪匹配:在重复匹配后面加上?问号,会匹配尽可能少的字符(并不严格)
2.4字符选择匹配
使用|来实现选择匹配,即多个选择中选一个
a|b|c 配a或者b或则c
2.5正则字符串的替换操作,生成字符串数组
public static void main(String[] args) { String str="78ty4589jk78"; String[] parts=str.split("[0-9]+"); String newstr=str.replaceAll("[0-9]", "*"); System.out.println(Arrays.toString(parts)); System.out.println(newstr); //将之前的数字替换为字母 //所有符合的正则的字符串替换为* }
2.6正则表达式字符类
- [ ] [abc] 匹配abc中任意一个字符,类似 a|b|c
- [^ ] [^abc] 匹配非abc的任意一个字符
- [ - ] [0-9]、[a-z]、[a-zA-Z] 匹配范围内的任意一个字符
- 注意:字符类中的元字符(\除外),会被自动转义为普通字符,比如 [.] 等同于 [\.]
- \w 代表一个单词字符,类似于[a-zA-Z0-9_],有的语言中也可以匹配中文
- \W 代表一个非单词字符,类似于[^a-zA-Z0-9_]
- \d 代表一个数字字符,等同于[0-9]
- \D 代表一个非数字字符,等同于[^0-9]
- \s 代表一个空白字符
- \S 代表一个非空白字符
2.7正则表达式的案列
实现一个小爬虫,存放在E 盘的main2文件下
1 package hh; 2 import java.io.FileOutputStream; 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.io.OutputStream; 6 import java.net.*; 7 public class abc { 8 public static void main(String []args) 9 { 10 InputStream inpustream=null; 11 FileOutputStream outputstream=null; 12 13 try { 14 long start=System.currentTimeMillis(); 15 int i=0; 16 for(i=1;i<550;i++) 17 { URL url=new URL("http://www.bokee.com//topic/images/%E6%9C%AA%E6%A0%87%E9%A2%98-2("+i+").jpg"); 18 inpustream=url.openStream(); 19 20 // http://www.bokee.com//topic/images/%E6%9C%AA%E6%A0%87%E9%A2%98-1(530).jpg 21 // <img src="/_upload/article/images/66/b6/810dfe294d62aa81fba5ca1baef9/57c958b6-72e8-4331-a431-24b06039b649.jpg"> 22 // <img src="/_upload/article/images/99/a1/416529614b32ba6a2f824bbbafae/04b85865-f1b9-4128-b33f-04eff1e81c5a.jpg"> 23 outputstream=new FileOutputStream("E://main2//"+i+".png"); 24 IOUtils.copy(inpustream, outputstream); 25 } 26 long end=System.currentTimeMillis(); 27 System.out.println("下载成功,耗时"+(start-end)+"毫秒"); 28 } 29 catch (MalformedURLException e) { 30 // TODO Auto-generated catch block 31 e.printStackTrace(); 32 } catch (IOException e) { 33 // TODO Auto-generated catch block 34 e.printStackTrace(); 35 } 36 } 37 }
3.多线程编程
在线程之前,先提一下进程,进程就好比我们运行的一个一个程序,每一个程序都是一个进程,它拥有子的进程id号 简称pid。进程里面又可以继续分为线程,而多线程则是一个进程里的进程。
在通常情况下,进程是遵循时间片轮询算法的,它是经过就绪队列,阻塞队列和执行 三个步骤。由于计算机的运行速度非常快,它自己运行一个程序再运行下一个程序给人的感觉就像是同一个时间发生的一样。
线程与集成相似,称为轻量级的进程。多线程的目的是使一个程序在一个时间内分别做一个或者多个事情
简单案列:执行一个新的线程
1 public class text { 2 public static void main(String []args) 3 { 4 mythread test1=new mythread(); 5 test1.start(); 6 } 7 } 8 class mythread extends Thread 9 { 10 @Override 11 public void run() 12 { 13 System.out.println(" 执行了"); 14 } 15 } 16 3.1 Runnable接口 17 除了通过继承Thread类来是实现一个新的线程,也可以通过继承Runnable接口来实现,实现方法如下,new一个新的线程 在线程里newRunnable接口 并且实现接口里的方法。 18 public static void main(String []args) 19 { 20 Thread thread =new Thread(new Runnable() 21 { 22 23 @Override 24 public void run() { 25 // TODO Auto-generated method stub 26 System.out.println("Runnable 接口实现多线程"); 27 } 28 //runnable 29 //sleep 执行完成后立即进入睡眠状态 30 }); 31 thread.start(); 32 33 } 34 }
3.2sleep线程
如何使一个线程暂停一段时间,Thread.sleep会让线程休眠一段时间。只是休眠,
计时器
1 public class sleeptext { 2 public static void main(String[] args) 3 { 4 System.out.println("倒计时开始"); 5 for(int i=10;i>0;i--) 6 { 7 try 8 { 9 Thread.sleep(1000); 10 //倒计时装备 11 } 12 catch (InterruptedException e) 13 { 14 System.out.println("线程暂停失败"+e.getMessage()); 15 } 16 System.out.println(i); 17 //希望每隔一秒倒数一次 18 } 19 } 20 }
}
3.3线程问题,如果在A线程中存入数据,在B线程中读取数据,C中又在删除数据,这样就会造成数据错误,程序出错的或其他情况
由于计算机执行速度太快等的原因。
3.4锁
Sync同步锁
Java中每个对象都有一把锁,同一时刻只能有一个线程持有这把锁。线程可以使用synchronized关键字向系统申请某个对象的锁,得到锁之后,别的线程再申请该锁时,就只能等待。持有锁的线程在这次操作完成后,可以释放锁,以便其他线程可以获得锁
1 import java.util.ArrayList; 2 import java.util.List; 3 public class Synchronized { 4 public static void main(String args[]) 5 { 6 Data data=new Data(); 7 Thread thread1=new Thread(new Runnable(){ 8 @Override 9 public void run() { 10 data.bianliList(); 11 } 12 }); 13 Thread thread2=new Thread(new Runnable(){ 14 @Override 15 public void run() { 16 data.cleadlist(); 17 } 18 }); 19 thread1.start(); 20 thread2.start(); 21 } 22 } 23 class Data{ 24 private List<Integer>list; 25 public Data() 26 { 27 list=new ArrayList<Integer>(); 28 synchronized (list){ 29 for(int i=0;i<1000000;i++) 30 { 31 list.add(i); 32 33 } 34 } 35 } 36 37 public synchronized void bianliList() 38 { 39 40 for(int i=0;i<list.size();i++) 41 { 42 System.out.println(list.get(i)); 43 44 } 45 46 } 47 public synchronized void cleadlist() 48 { 49 list.clear(); 50 51 } 52 }
但需要注意,所有需要同步的线程必须都申请同一个对象的锁,当申请不同的锁或者有的线程没有使用synchronized时,同步锁机制就会失效
3.5等待唤醒机制 wait notify
均实现Runnable接口来实现线程,线程1在线程中等待,线程2来唤醒线程1 并继续执行
1 public class waitnotify 2 { 3 /* 4 * 需要多个线程来通知或者唤醒机制 5 */ 6 public static void main(String[] args) 7 { 8 Object lockObject =new Object(); 9 // thread1.start(); 10 // thread2.start(); 11 Thread thread1=new Thread(new Runnable() 12 { 13 @Override 14 public void run() { 15 synchronized(lockObject){ 16 17 try{ 18 System.out.println("线程1即将在lock上等待"); 19 //可能会导致线程在永久等待的 20 lockObject.wait(); 21 System.out.println("线程1收到了通知 并且获得锁继续执行"); 22 23 } 24 catch(InterruptedException e) 25 { 26 e.printStackTrace(); 27 } 28 } 29 30 } 31 32 }); 33 Thread thread2=new Thread(new Runnable() 34 { 35 36 @Override 37 public void run() { 38 // TODO Auto-generated method stub 39 synchronized(lockObject) 40 { 41 try { 42 Thread.sleep(2000); 43 } catch (InterruptedException e) { 44 // TODO Auto-generated catch block 45 e.printStackTrace(); 46 } 47 System.out.println("线程2即将随机通知一个在lock上等待的线程"); 48 lockObject.notify(); //如果有多个线程则调用all方法 49 // 三个线程被通知之后都会通知阻塞队列 50 } 51 } 52 }); 53 thread2.start(); 54 thread1.start(); 55 56 } 57 /* 58 * 等待通知机制 59 * 60 * 61 */ 62 }
结果
线程1即将在lock上等待
线程2即将随机通知一个在lock上等待的线程
线程1收到了通知 并且获得锁继续执行
3.6生产者消费者
生产者和消费者模型是典型的队列模型,遵循先进先出的规则,一个生产一个消费,采用add 和remove 的方式来加强对等待唤醒机制和队列模型的印象
1 import java.util.LinkedList; 2 import java.util.List; 3 4 public class producer { 5 6 public static void main(String []args) 7 { 8 List<Integer>buffer=new LinkedList<Integer>(); 9 int maxSize=10; 10 pro producer =new pro(buffer, maxSize); 11 Conn consumer=new Conn(buffer); 12 producer.start(); 13 consumer.start(); 14 15 } 16 } 17 18 class pro extends Thread{ 19 private List<Integer>buffer; 20 private int maxSize; 21 public pro(List<Integer>buffer,int maxSize) 22 { 23 this.buffer=buffer; 24 this.maxSize=maxSize; 25 } 26 27 public void run() 28 { 29 int id=0; 30 while(true) 31 { 32 33 synchronized (buffer) 34 { 35 if(buffer.size()<10) 36 { id++;//表示生产了一个产品 37 buffer.add(id); 38 //表示把产品放入kongpanzi 39 System.out.println("生产了一个产品,并将通知消费者可以消费了"); 40 buffer.notify();//通知消费者线程可以消费了 41 } 42 else 43 { 44 System.out.println("已经没有空盘子了 消费者开始等待"); 45 46 } 47 try{ 48 buffer.wait(); 49 } 50 catch(InterruptedException e) 51 { 52 e.printStackTrace(); 53 } 54 } 55 56 } 57 58 } 59 60 } 61 class Conn extends Thread 62 { 63 private List<Integer>buffer; 64 public Conn(List<Integer>buffer) 65 { 66 this.buffer=buffer; 67 } 68 @Override 69 public void run() 70 { 71 while(true) 72 { 73 synchronized (buffer) { 74 if(buffer.size()>0) 75 { 76 Integer id=buffer.remove(0); 77 System.out.println("消费者消费了产品并将"+id+"通知生产者可以生产了"); 78 buffer.notify();//通知生产者开始生产了 79 } 80 else 81 { 82 try{ 83 System.out.println("全部都是空盘子消费者只能等待"); 84 buffer.wait(); 85 86 } 87 catch(InterruptedException e) 88 { 89 e.printStackTrace(); 90 } 91 92 } 93 } 94 } 95 } 96 }
结果
生产了一个产品,并将通知消费者可以消费了
消费者消费了产品并将48117通知生产者可以生产了
3.7守护线程
守护线程是一个特别的线程,可以为所有的线程进行服务,当所有线程都执行结束后。守护线程也就消失了
1 public class Daemon { 2 public static void main(String[] args) 3 { 4 Thread thread1 =new Thread (new Runnable() 5 { 6 @Override 7 public void run() 8 { 9 while(true) 10 { 11 System.out.println("守护线程主要提供某种服务"); 12 try 13 { 14 Thread.sleep(1000); 15 } 16 catch(InterruptedException e ) 17 { 18 e.printStackTrace(); 19 } 20 } 21 } 22 }); 23 Thread thread2 =new Thread(new Runnable() 24 { 25 @Override 26 public void run() { 27 // TODO Auto-generated method stub 28 try{ 29 Thread.sleep(5000); 30 } 31 catch(InterruptedException e) 32 { 33 e.printStackTrace(); 34 } 35 } 36 }); 37 thread1.start(); 38 thread2.start(); 39 } 40 }
3.8线程打断机制
使用线程2来打断线程1并执行里面的代码
1 public class 打断 2 { 3 //就绪队列 调度执行 4 public static void main(String []args) 5 { 6 Thread thread1 = new Thread(new Runnable() { 7 @Override 8 public void run() { 9 // TODO Auto-generated method stub 10 System.out.println("线程1即将进入阻塞状态"); 11 try { 12 Thread.sleep(10000); 13 } catch (InterruptedException e) { 14 // TODO Auto-generated catch block 15 System.out.println("线程1打断开始执行里面的代码"); 16 17 e.printStackTrace(); 18 } 19 } 20 }); 21 Thread thread2 = new Thread(new Runnable() { 22 23 @Override 24 public void run() { 25 // TODO Auto-generated method stub 26 try { 27 Thread.sleep(10000); 28 } catch (InterruptedException e) { 29 // TODO Auto-generated catch block 30 e.printStackTrace(); 31 } 32 thread1.interrupt();//打断线程1 33 34 } 35 }); 36 thread1.start(); 37 thread2.start(); 38 } 39 }
3.9通过线程的优先级来设置哪个线程优先启动
thread4.setPriority(Thread.MAX_PRIORITY);
最大线程的优先级
1 public class PriorityTest 2 { 3 public static void main(String []args) 4 { 5 MyThread2 thread0 =new MyThread2(); 6 MyThread2 thread1=new MyThread2(); 7 MyThread2 thread2 =new MyThread2(); 8 MyThread2 thread3 =new MyThread2(); 9 MyThread2 thread4 =new MyThread2(); 10 //最大的优先级 最高为10 默认为5 11 // 依次启动 12 thread4.setPriority(Thread.MAX_PRIORITY); 13 //但是在采用时间片轮询算法的操作系统效果并不明显 14 thread0.start(); 15 thread1.start(); 16 thread2.start(); 17 thread3.start(); 18 thread4.start(); 19 } 20 } 21 class MyThread2 extends Thread { 22 23 public void run() 24 { 25 for(int i=0;i<2000;i++) 26 { 27 try{ 28 Thread.sleep(1); 29 } 30 catch(InterruptedException e) 31 { 32 e.printStackTrace(); 33 34 } 35 // Thread.currentThread(); 36 //返回线程执行对象 37 System.out.println(Thread.currentThread().getName()+"在"+System.currentTimeMillis()+"执行完成"); 38 } 39 } 40 }
2018-01-08 11:40:23