不管是JAVA,还是.NET。我们常常会看到空异常(NullPointerException)。这种异常都是在运行的过程中出现。往往是变量是一个null值。但是你引用这个变量的后继字段或是方法。所以我们代码里面常常会出现if (变量!=null)的相关操作。
如果你是一个.NET开发人员的话,那么你一定知道.NET的可以为空的数据类型。同样子java8引入了一个Optional类型,目地是为了决解为空带来的一系列问题。Optional类提供了俩个静态的方法

  • of方法:创建一个非空的Optional类型。
  • ofNullable方法:创建一个可以为空的Optional类型。

让我们一起看一下用法吧。

 package com.aomi;

 import java.util.HashMap;
import java.util.Map;
import java.util.Optional; public class Main {
private static Map<String, String> maps = new HashMap<String, String>(); public static void main(String[] args) {
// TODO Auto-generated method stub maps.put("aomi", "val1");
maps.put("key1", "val2"); String val = getValue("aaa"); Optional<String> optionalVal = Optional.ofNullable(val); if(optionalVal.isPresent())
{
System.out.println(val.replace("a", "b"));
}
else
{
System.out.println("拿到变量值为空");
}
} public static String getValue(String key) {
if (maps.containsKey(key))
return maps.get(key);
return null;
}
}

运行结果:

isPresent方法用于判断当前的变量是否为空。从某意义上来讲笔者觉得这好像并没有多大的好处。同样子我们要用isPresent来判断是否为空。那么跟写if(变量!=null)有什么分别。所以笔者打算换一换。

 package com.aomi;

 import java.util.HashMap;
import java.util.Map;
import java.util.Optional; public class Main {
private static Map<String, String> maps = new HashMap<String, String>(); public static void main(String[] args) {
// TODO Auto-generated method stub maps.put("aomi", "val1");
maps.put("key1", "val2"); String notNullVal = getValue("aomi");
String nullVal = getValue("aaa"); Optional<String> optNotNullVal = Optional.ofNullable(notNullVal);
Optional<String> optNullVal = Optional.ofNullable(nullVal); System.out.println(optNotNullVal.orElse("拿到变量值为空"));
System.out.println(optNullVal.orElse("拿到变量值为空"));
} public static String getValue(String key) {
if (maps.containsKey(key))
return maps.get(key);
return null;
}
}

上面的代码是这样子的。笔者拿俩个变量,一个变量是为空的。一个不为空。然后笔者用Optional类的orElse来做文章。显示如下。

当然Optional类里面提供了几个用于获得值的方法。

  • get方法:就是用于获得值,如果当前的Optional类是一个有值的变量,那么就返回值。如果没有的话,不好意思!他会报错。
  • orElse方法:表示如果为空的话,我就返回方法给定的值。否则返回当前的值。
  • orElseGet方法:表示如果为空的话,执行一个回调的方法函数。你可以传入一个lambda表达。
  • orElseThrow方法:表示如果为空的话,回返一个异常,可以是一个自定义的异常。

以上这些方法,笔者认为并不能说明Optional类的特别之处。如下

 package com.aomi;

 import java.util.HashMap;
import java.util.Map;
import java.util.Optional; public class Main {
private static Map<String, String> maps = new HashMap<String, String>(); public static void main(String[] args) {
// TODO Auto-generated method stub maps.put("aomi", "val1");
maps.put("key1", "val2"); String notNullVal = getValue("aomi"); Optional<String> optNotNullVal = Optional.ofNullable(notNullVal); Optional<String> optNullNewVal = optNotNullVal.map(ss -> ss.replace("a", "b")); System.out.println(optNullNewVal.orElse("拿到变量值为空"));
} public static String getValue(String key) {
if (maps.containsKey(key))
return maps.get(key);
return null;
}
}

运行结果:

我们可以到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方法。没有错。还真的有。如下。

 package com.aomi;

 import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional; public class Main {
private static Map<String, String> maps = new HashMap<String, String>(); public static void main(String[] args) {
// TODO Auto-generated method stub maps.put("aomi", "vbl1");
maps.put("key1", "val2"); String notNullVal = getValue("aomi"); Optional<String> optNotNullVal = Optional.ofNullable(notNullVal); Optional<String> optNullNewVal = optNotNullVal.filter( ss->ss.contains("a")).map(ss->ss.replace("a", "b")); System.out.println(optNullNewVal.orElse("拿到变量值为空"));
} public static String getValue(String key) { if(maps.containsKey(key))
return maps.get(key);
return "map";
}
}

笔者找出含有’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

 package com.aomi;

 public class Main {

     public static void main(String[] args) {
// TODO Auto-generated method stub Thread th1 = new Thread() {
@Override
public void run() {
System.out.println("这是一个Thread副线程");
}
}; th1.start(); Thread th2 = new Thread(new Runnable() { @Override
public void run() {
System.out.println("这是一个Runnable副线程");
}
}); th2.start(); try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} System.out.println("这是一个主线程");
} }

运行结果:

我们可以看到代码中的俩种方式了吧。这俩个方式都只有一个毛病。没有办法实现返回值的功能。所以引入了Future接口。如下

 package com.aomi;

 import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask; public class Fmain {
public static void main(String[] args) { FutureTask<String> task = new FutureTask<>(new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(1000);
return "i am aomi";
}
}); new Thread(task).start(); try {
System.out.println("主线程: 结果=" + task.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
}

运行结果:

我可以看到一个叫Callable接口。是里面的call方法和Runnable方法有一点像。只是一个有返回值,一个没有。FutureTask类同时也提了很多方法。比如上的代码笔者在改改。加入判断是否取消了。如果没有取消的话,就取消掉他。然后也去获取他的值。

 package com.aomi;

 import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask; public class Fmain {
public static void main(String[] args) { FutureTask<String> task = new FutureTask<>(new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(1000);
System.out.println("副线程:返回值=i am aomi");
return "i am aomi";
}
}); new Thread(task).start(); try {
if (!task.isCancelled())
{
task.cancel(true);
System.out.println("取消副线程");
System.out.println("主线程: 结果=" + task.get());
}
else
{
System.out.println("主线程: 结果=" + task.get());
} } catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
}

运行结果:

看到了没有被取消了。同时你去获得取消线程的结果时,会发生异常。有没有.NET的程序员,感觉像不像.NET的任务(Task)。 事实上有上面的功能大部业务都可以实现了。但是JAVA8还是又引一个叫CompletableFuture类。相对于Future接口增加了很多方法。如下获得异步里面的结果。

 package com.aomi;

 import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException; public class Cmain { public static void main(String[] args) {
// TODO Auto-generated method stub CompletableFuture<String> future = new CompletableFuture<>(); new Thread(new Runnable() { @Override
public void run() { try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} future.complete("i am a CompletableFuture"); }
}).start(); try { System.out.println(future.get()); } catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } }

运行结果:

笔者在线程里面睡了2000秒。所以你们运行之个例子的时候,会发现慢了2秒才显示结果。说明future.get()会等线程的结果。事实上FutureTask类也是一样子。所以CompletableFuture类提供一系列的功能组合。只要设计好的话,性能会提高很多。

 package com.aomi;

 import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory; public class Dmain { public static void main(String[] args) {
// TODO Auto-generated method stub CompletableFuture<String> oneFuture = CompletableFuture.supplyAsync(() -> { System.out.println("supplyAsync用于新建");
return "2011";
}); CompletableFuture<Long> twoFuture = oneFuture.thenApply((ss) -> {
System.out.println("thenApply用于转化");
return Long.parseLong(ss);
}); CompletableFuture<Long> threeFuture = twoFuture.thenCompose(val -> {
System.out.println("thenCompose用于组合俩个CompletableFuture,但是依赖上一个CompletableFuture");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} return CompletableFuture.supplyAsync(() ->
{
long result = val * 2;
System.out.println("thenCompose的结果是:"+ result);
return result;
} );
}); CompletableFuture<String> otherFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("用于thenCombine的测试 上面的结果+4");
return "4";
}); CompletableFuture<Long> finalFuture = threeFuture.thenCombine(otherFuture, (arg1, arg2) -> {
return arg1 + Long.parseLong(arg2);
}); finalFuture.thenAccept((ss) -> {
System.out.println("thenAccept用于处理相关的结果数据");
}); finalFuture.thenRun(() -> {
System.out.println("thenRun用于异步完成,执行相关的操作");
}); try { System.out.println(finalFuture.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } }

运行结果:

这个个方法的作用笔者略微的列了出来。想要加深的话,你们可能最好在去找一些资料。关于CompletableFuture的教程网络上很多。

JAVA8给我带了什么——Optional和CompletableFuture的更多相关文章

  1. JAVA8给我带了什么——流的概念和收集器

    到现在为止,笔者不敢给流下定义,从概念来讲他应该也是一种数据元素才是.可是在我们前面的代码例子中我们可以看到他更多的好像在表示他是一组处理数据的行为组合.这让笔者很难去理解他的定义.所以笔者不表态.各 ...

  2. JAVA8给我带了什么——lambda表达

    这此年来我一直从事.NET的开发.对于JAVA我内心深处还是很向往的.当然这并不是说我不喜欢.NET.只是觉得JAVA也许才是笔者最后的归处.MK公司是以.NET起家的.而笔者也因为兄弟的原因转行.N ...

  3. Java8新特性(三)——Optional类、接口方法与新时间日期API

    一.Optional容器类 这是一个可以为null的容器对象.如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象. 查看结构图可以看到有如下常用方法: of(T)—— ...

  4. 【Java8新特性】不了解Optional类,简历上别说你懂Java8!!

    写在前面 最近,很多读者出去面试都在Java8上栽了跟头,事后自己分析,确实对Java8的新特性一知半解.然而,却在简历显眼的技能部分写着:熟练掌握Java8的各种新特性,能够迅速使用Java8开发高 ...

  5. JAVA8给我带了什么——并行流和接口新功能

    流,确定是笔者内心很向往的天堂,有他之后JAVA在处理数据就变更加的灵动.加上lambda表达不喜欢都不行.JAVA8也为流在提供另一个功能——并行流.即是有并行流,那么是不是也有顺序流.没有错.我前 ...

  6. JAVA8给我带了什么——流(入门)

    JAVA8有一个新功能——流.笔者简单的看一下流.然后默默的闭上眼睛.感叹一声:这不是.NET里面的Linq吗?如果你们当中有谁做过.NET程序员的话,对于流的学习其实帮助是很大的.但是要明白你现在是 ...

  7. Java8学习笔记(六)--Optional

    前言 身为一名Java程序员,大家可能都有这样的经历:调用一个方法得到了返回值却不能直接将返回值作为参数去调用别的方法.我们首先要判断这个返回值是否为null,只有在非空的前提下才能将其作为其他方法的 ...

  8. Java8的新特性--Optional

    目录 Optional 一.Optional类是什么? 二.Optional类常用的方法 1. 创建Optional实例 1.1 Optional.of(T) 1.2 Optional.empty() ...

  9. Java8系列 (五) Optional类

    概述 在Java8之前, 如果需要对一个变量做一次 null 检查, 通常会像下面这样写 T t = service1.query(); if (t != null) { K k = service2 ...

随机推荐

  1. 值类型和引用类型的区别,struct和class的区别

    C#值类型和引用类型 1.简单比较 值类型的变量直接存储数据,而引用类型的变量持有的是数据的引用,数据存储在数据堆中. 值类型(value type):byte,short,int,long,floa ...

  2. 12.14 Daily Scrum

      Today's Task Tomorrow's Task 丁辛 实现和菜谱相关的餐厅列表. 实现和菜谱相关的餐厅列表.             邓亚梅             美化搜索框UI. 美 ...

  3. 《Linux内核分析》课程第七周学习总结

    姓名:何伟钦 学号:20135223 ( *原创作品转载请注明出处*) ( 学习课程:<Linux内核分析>MOOC课程http://mooc.study.163.com/course/U ...

  4. Linux第五周学习总结

    作者:黎静 一.知识点总结 (一)给MenuOS增加time和time-asm命令 1.更新menu代码到最新版 2.test.c中main函数里,增加MenuConfig() 3.增加对应的两个函数 ...

  5. 四则运算安卓版ver.mk3

    在原有的基础上做了些许改动以及添加了一点小功能,以下是代码: package com.example.add; import java.io.File; import com.example.add. ...

  6. CMake系列之二:入门案例-单个源文件

    编写一个源码文件 如下 #include<stdio.h> #include<stdlib.h> double power(double base,int exponent) ...

  7. 基于C#.NET的高端智能化网络爬虫(二)(攻破携程网)

    本篇故事的起因是携程旅游网的一位技术经理,豪言壮举的扬言要通过他的超高智商,完美碾压爬虫开发人员,作为一个业余的爬虫开发爱好者,这样的言论我当然不能置之不理.因此就诞生了以及这一篇高级爬虫的开发教程. ...

  8. python2.7.x的字符串编码到底什么鬼?(中文和英文的处理)

    一直以来我其实一直对python的编码弄得非常晕,能正常编码,也能处理一些情况.但是始终不明白有些问题究竟为何出,原因是什么,为什么要这样用. 今天晚上正好好好研究了一番解答了自己心中的困惑. Q:p ...

  9. RabbitMQ基础知识详解

    什么是MQ? MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.MQ是消费-生产者模型的一个典型的代表,一端往消息队列中不断写入消息,而另一端则可以读取队列中 ...

  10. 多条件查询 仿淘宝URL传参方式

    ---恢复内容开始--- 最近项目在做一个电商网站,网站涉及到前后台交互的多条件查询,类似于淘宝的多条件查询,图片如下 此类查询主要涉及到的问题有: 1.如何记忆查询参数 2.如何前后台传值 3.中文 ...