不论是JAVA,仍是.NET。咱们经常会看到空异常(NullPointerException)。这种异常都是在运行的过程当中出现。每每是变量是一个null值。可是你引用这个变量的后继字段或是方法。因此咱们代码里面经常会出现if (变量!=null)的相关操做。
若是你是一个.NET开发人员的话,那么你必定知道.NET的能够为空的数据类型。一样子java8引入了一个Optional类型,目地是为了决解为空带来的一系列问题。Optional类提供了俩个静态的方法java
让咱们一块儿看一下用法吧。程序员
1 package com.aomi; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 import java.util.Optional; 6 7 public class Main { 8 private static Map<String, String> maps = new HashMap<String, String>(); 9 10 public static void main(String[] args) { 11 // TODO Auto-generated method stub 12 13 maps.put("aomi", "val1"); 14 maps.put("key1", "val2"); 15 16 String val = getValue("aaa"); 17 18 Optional<String> optionalVal = Optional.ofNullable(val); 19 20 if(optionalVal.isPresent()) 21 { 22 System.out.println(val.replace("a", "b")); 23 } 24 else 25 { 26 System.out.println("拿到变量值为空"); 27 } 28 } 29 30 public static String getValue(String key) { 31 if (maps.containsKey(key)) 32 return maps.get(key); 33 return null; 34 } 35 }
运行结果:网络
isPresent方法用于判断当前的变量是否为空。从某意义上来说笔者以为这好像并无多大的好处。一样子咱们要用isPresent来判断是否为空。那么跟写if(变量!=null)有什么分别。因此笔者打算换一换。多线程
1 package com.aomi; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 import java.util.Optional; 6 7 public class Main { 8 private static Map<String, String> maps = new HashMap<String, String>(); 9 10 public static void main(String[] args) { 11 // TODO Auto-generated method stub 12 13 maps.put("aomi", "val1"); 14 maps.put("key1", "val2"); 15 16 String notNullVal = getValue("aomi"); 17 String nullVal = getValue("aaa"); 18 19 Optional<String> optNotNullVal = Optional.ofNullable(notNullVal); 20 Optional<String> optNullVal = Optional.ofNullable(nullVal); 21 22 System.out.println(optNotNullVal.orElse("拿到变量值为空")); 23 System.out.println(optNullVal.orElse("拿到变量值为空")); 24 } 25 26 public static String getValue(String key) { 27 if (maps.containsKey(key)) 28 return maps.get(key); 29 return null; 30 } 31 }
上面的代码是这样子的。笔者拿俩个变量,一个变量是为空的。一个不为空。而后笔者用Optional类的orElse来作文章。显示以下。异步
固然Optional类里面提供了几个用于得到值的方法。ide
以上这些方法,笔者认为并不能说明Optional类的特别之处。以下函数
1 package com.aomi; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 import java.util.Optional; 6 7 public class Main { 8 private static Map<String, String> maps = new HashMap<String, String>(); 9 10 public static void main(String[] args) { 11 // TODO Auto-generated method stub 12 13 maps.put("aomi", "val1"); 14 maps.put("key1", "val2"); 15 16 String notNullVal = getValue("aomi"); 17 18 19 Optional<String> optNotNullVal = Optional.ofNullable(notNullVal); 20 21 Optional<String> optNullNewVal = optNotNullVal.map(ss -> ss.replace("a", "b")); 22 23 System.out.println(optNullNewVal.orElse("拿到变量值为空")); 24 } 25 26 public static String getValue(String key) { 27 if (maps.containsKey(key)) 28 return maps.get(key); 29 return null; 30 } 31 }
运行结果:性能
咱们能够到Optional类提供了一个map方法。这个功能跟之前讲到的流的map有一点相似。大家能够看到笔者在上面经过map方法来把'a'字符替换为‘b’。最后val1变成为vbl1。若是笔者还想把‘l‘替换为’r‘。后面在增长一个Map以下测试
Optional<String> optNullNewVal = optNotNullVal.map(ss -> ss.replace("a", "b")).map(ss->ss.replace("l","r"));
即然有map方法了。是否是也主是有filter方法。没有错。还真的有。以下。spa
1 package com.aomi; 2 3 import java.util.HashMap; 4 import java.util.List; 5 import java.util.Map; 6 import java.util.Optional; 7 8 public class Main { 9 private static Map<String, String> maps = new HashMap<String, String>(); 10 11 public static void main(String[] args) { 12 // TODO Auto-generated method stub 13 14 maps.put("aomi", "vbl1"); 15 maps.put("key1", "val2"); 16 17 String notNullVal = getValue("aomi"); 18 19 Optional<String> optNotNullVal = Optional.ofNullable(notNullVal); 20 21 Optional<String> optNullNewVal = optNotNullVal.filter( ss->ss.contains("a")).map(ss->ss.replace("a", "b")); 22 23 System.out.println(optNullNewVal.orElse("拿到变量值为空")); 24 } 25 26 public static String getValue(String key) { 27 28 if(maps.containsKey(key)) 29 return maps.get(key); 30 return "map"; 31 } 32 }
笔者找出含有’a‘字符的字串符。而后"a"替换 "b"。主要修改代码俩个地方。以下
1.把val1修改成vbl1。主要是让他有值,却不含有'a'字符。了为证实他能够过滤掉有‘a’的字符串
maps.put("aomi", "vbl1");
2.增长filter方法进行过滤。条件必须含有'a'
.filter( ss->ss.contains("a"))
运行结果:
JAVA为了空值的问题增长了Optional类。提功能了一系列功能。你们能够试着用用感受如何。
笔者记得好像是在JAVA5的时候,JAVA引一个Future接口。若是你没有印像的话,那大家有没有用到过FutureTask类呢。 之前要建立一个多线程的话,通常有俩种。一种是继承Thread;一种是实现Runnable
1 package com.aomi; 2 3 public class Main { 4 5 public static void main(String[] args) { 6 // TODO Auto-generated method stub 7 8 Thread th1 = new Thread() { 9 @Override 10 public void run() { 11 System.out.println("这是一个Thread副线程"); 12 } 13 }; 14 15 th1.start(); 16 17 18 Thread th2 = new Thread(new Runnable() { 19 20 @Override 21 public void run() { 22 System.out.println("这是一个Runnable副线程"); 23 } 24 }); 25 26 th2.start(); 27 28 try { 29 Thread.sleep(2000); 30 } catch (InterruptedException e) { 31 // TODO Auto-generated catch block 32 e.printStackTrace(); 33 } 34 35 System.out.println("这是一个主线程"); 36 } 37 38 }
运行结果:
咱们能够看到代码中的俩种方式了吧。这俩个方式都只有一个毛病。没有办法实现返回值的功能。因此引入了Future接口。以下
1 package com.aomi; 2 3 import java.util.concurrent.Callable; 4 import java.util.concurrent.ExecutionException; 5 import java.util.concurrent.FutureTask; 6 7 public class Fmain { 8 public static void main(String[] args) { 9 10 FutureTask<String> task = new FutureTask<>(new Callable<String>() { 11 @Override 12 public String call() throws Exception { 13 Thread.sleep(1000); 14 return "i am aomi"; 15 } 16 }); 17 18 new Thread(task).start(); 19 20 try { 21 System.out.println("主线程: 结果=" + task.get()); 22 } catch (InterruptedException e) { 23 // TODO Auto-generated catch block 24 e.printStackTrace(); 25 } catch (ExecutionException e) { 26 // TODO Auto-generated catch block 27 e.printStackTrace(); 28 } 29 30 } 31 }
运行结果:
我能够看到一个叫Callable接口。是里面的call方法和Runnable方法有一点像。只是一个有返回值,一个没有。FutureTask类同时也提了不少方法。好比上的代码笔者在改改。加入判断是否取消了。若是没有取消的话,就取消掉他。而后也去获取他的值。
1 package com.aomi; 2 3 import java.util.concurrent.Callable; 4 import java.util.concurrent.ExecutionException; 5 import java.util.concurrent.FutureTask; 6 7 public class Fmain { 8 public static void main(String[] args) { 9 10 FutureTask<String> task = new FutureTask<>(new Callable<String>() { 11 @Override 12 public String call() throws Exception { 13 Thread.sleep(1000); 14 System.out.println("副线程:返回值=i am aomi"); 15 return "i am aomi"; 16 } 17 }); 18 19 new Thread(task).start(); 20 21 try { 22 if (!task.isCancelled()) 23 { 24 task.cancel(true); 25 System.out.println("取消副线程"); 26 System.out.println("主线程: 结果=" + task.get()); 27 } 28 else 29 { 30 System.out.println("主线程: 结果=" + task.get()); 31 } 32 33 } catch (InterruptedException e) { 34 // TODO Auto-generated catch block 35 e.printStackTrace(); 36 } catch (ExecutionException e) { 37 // TODO Auto-generated catch block 38 e.printStackTrace(); 39 } 40 41 } 42 }
运行结果:
看到了没有被取消了。同时你去得到取消线程的结果时,会发生异常。有没有.NET的程序员,感受像不像.NET的任务(Task)。 事实上有上面的功能大部业务均可以实现了。可是JAVA8仍是又引一个叫CompletableFuture类。相对于Future接口增长了不少方法。以下得到异步里面的结果。
1 package com.aomi; 2 3 import java.util.concurrent.CompletableFuture; 4 import java.util.concurrent.ExecutionException; 5 6 public class Cmain { 7 8 public static void main(String[] args) { 9 // TODO Auto-generated method stub 10 11 CompletableFuture<String> future = new CompletableFuture<>(); 12 13 new Thread(new Runnable() { 14 15 @Override 16 public void run() { 17 18 try { 19 Thread.sleep(2000); 20 } catch (InterruptedException e) { 21 // TODO Auto-generated catch block 22 e.printStackTrace(); 23 } 24 25 future.complete("i am a CompletableFuture"); 26 27 } 28 }).start(); 29 30 31 try { 32 33 System.out.println(future.get()); 34 35 } catch (InterruptedException e) { 36 // TODO Auto-generated catch block 37 e.printStackTrace(); 38 } catch (ExecutionException e) { 39 // TODO Auto-generated catch block 40 e.printStackTrace(); 41 } 42 43 } 44 45 }
运行结果:
笔者在线程里面睡了2000秒。因此大家运行之个例子的时候,会发现慢了2秒才显示结果。说明future.get()会等线程的结果。事实上FutureTask类也是同样子。因此CompletableFuture类提供一系列的功能组合。只要设计好的话,性能会提升不少。
1 package com.aomi; 2 3 import java.util.concurrent.CompletableFuture; 4 import java.util.concurrent.ExecutionException; 5 import java.util.concurrent.Executor; 6 import java.util.concurrent.Executors; 7 import java.util.concurrent.ThreadFactory; 8 9 public class Dmain { 10 11 public static void main(String[] args) { 12 // TODO Auto-generated method stub 13 14 CompletableFuture<String> oneFuture = CompletableFuture.supplyAsync(() -> { 15 16 System.out.println("supplyAsync用于新建"); 17 return "2011"; 18 }); 19 20 CompletableFuture<Long> twoFuture = oneFuture.thenApply((ss) -> { 21 System.out.println("thenApply用于转化"); 22 return Long.parseLong(ss); 23 }); 24 25 CompletableFuture<Long> threeFuture = twoFuture.thenCompose(val -> { 26 System.out.println("thenCompose用于组合俩个CompletableFuture,可是依赖上一个CompletableFuture"); 27 try { 28 Thread.sleep(2000); 29 } catch (InterruptedException e) { 30 // TODO Auto-generated catch block 31 e.printStackTrace(); 32 } 33 34 return CompletableFuture.supplyAsync(() -> 35 { 36 long result = val * 2; 37 System.out.println("thenCompose的结果是:"+ result); 38 return result; 39 } 40 41 ); 42 }); 43 44 CompletableFuture<String> otherFuture = CompletableFuture.supplyAsync(() -> { 45 System.out.println("用于thenCombine的测试 上面的结果+4"); 46 return "4"; 47 }); 48 49 CompletableFuture<Long> finalFuture = threeFuture.thenCombine(otherFuture, (arg1, arg2) -> { 50 return arg1 + Long.parseLong(arg2); 51 }); 52 53 finalFuture.thenAccept((ss) -> { 54 System.out.println("thenAccept用于处理相关的结果数据"); 55 }); 56 57 finalFuture.thenRun(() -> { 58 System.out.println("thenRun用于异步完成,执行相关的操做"); 59 }); 60 61 try { 62 63 System.out.println(finalFuture.get()); 64 } catch (InterruptedException e) { 65 // TODO Auto-generated catch block 66 e.printStackTrace(); 67 } catch (ExecutionException e) { 68 // TODO Auto-generated catch block 69 e.printStackTrace(); 70 } 71 72 } 73 74 }
运行结果:
这个个方法的做用笔者略微的列了出来。想要加深的话,大家可能最好在去找一些资料。关于CompletableFuture的教程网络上不少。