一、optional
- 背景:当调用一个方法得到了返回值时却不能直接将返回值作参数直接去调用别的方法,我们大家首先要判断这个返回值是否为null,只有在非空的前提下才能将其作为其他方法的参数。而Google Guava的外部API就解决了这个问题,一些JVM编程语言如Scala也解决了这个问题,而java8也参照Guava引入了Optional这个类解决这一问题。
- 使用
- 依据一个 非null空值创建一个optional
Car car = null ;Optional
如果car是一个空值,这段代码会立即抛出NullPointerException,而不是等到试图访问car属性的时候carOpt = Optional.of(car) ; - 可接受null的optional
Car car = null ;Optional
carOpt = Optional.ofNullable(car) ; 如果car是空那么carOpt就是一个空对象,获取对象中的值的时候依然会抛出异常
注意:Optional在设计的时候没有考虑做为类的字段使用,所以它并未实现序列化接口,所以某些要求序列的库或框架中使用Optional有可能会引发应用故障,常用API请查看官网
二、Stream
- 介绍 Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念。它也不同于 StAX 对 XML 解析的 Stream,也不是 Amazon Kinesis 对大数据实时处理的 Stream。 Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。 Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程。通常编写并行代码很难而且容易出错, 但使用 Stream API 无需编写一行多线程的代码,就可以很方便地写出高性能的并发程序。所以说,Java 8 中首次出现的 java.util.stream 是一个函数式语言+多核时代综合影响的产物
- 操作:Stream操作被分为中间操作和终点操作
-
中间操作返回一个新的Stream。这些中间操作是延迟的,执行一个中间操作比如filter实际上不会真的做过滤操作,而是创建一个新的Stream,当这个新的Stream被遍历的时候,它里头会包含有原来Stream里符合过滤条件的元素。
-
终点操作比如说forEach或者sum会遍历Stream从而产生最终结果或附带结果。终点操作执行完之后,Stream管道就被消费完了,不再可用。在几乎所有的情况下,终点操作都是即时完成对数据的遍历操作。
Stream的另外一个价值是Stream创造性地支持并行处理。
-
-
代码示例
import java.io.File;import java.io.IOException;import java.nio.charset.StandardCharsets;import java.nio.file.Files;import java.nio.file.Path;import java.util.Arrays;import java.util.Collection;import java.util.List;import java.util.Map;import java.util.stream.Collectors;import java.util.stream.Stream;public class Streams { private enum Status{ OPEN,CLOSE; } private static final class Task{ private Status status; private Integer points; Task(Status status,Integer points){ this.status = status; this.points = points; } public Status getStatus(){ return status; } public Integer getPoints(){ return points; } public String toString(){ return String.format("[%s,%d]", status,points); } } public static void main(String[] args) throws IOException { //初始化tasks final Collection
tasks = Arrays.asList(new Task(Status.OPEN,5) ,new Task(Status.OPEN,15),new Task(Status.CLOSE,10)); //过滤 final long totalPointsOfOpenTasks = tasks. stream() .filter( task -> task.getStatus() == Status.OPEN) .mapToInt( Task::getPoints).sum(); System.out.println(totalPointsOfOpenTasks);//20 //分组 Map > map = tasks.stream().collect(Collectors.groupingBy(Task :: getStatus)); System.out.println(map); System.out.println(map.get(Status.OPEN)); System.out.println(map.get(Status.CLOSE)); //计算总和 final double totalPoints = tasks .stream() .parallel() .map( task -> task.getPoints() ) // or map( Task::getPoints ) .reduce( 0, Integer::sum ); System.out.println( "Total points (all tasks): " + totalPoints ); //计算整个集合中每个task分数(或权重)的平均值 final Collection result = tasks.stream().mapToInt(Task :: getPoints).asLongStream() .mapToDouble(points -> points / totalPoints) .boxed() .mapToLong(weigth -> (long)(weigth * 100)) .mapToObj(percentage -> percentage + "%") .collect(Collectors.toList()); System.out.println(result); //读取文件 String filename = "E:\\code\\123\\src\\test\\java\\AppTest.java"; final Path path = new File( filename ).toPath(); try( Stream< String > lines = Files.lines( path, StandardCharsets.UTF_8 )){ lines.onClose( () -> System.out.println("Done!") ).forEach( System.out::println ); } }}
参考地址:http://mrhe.top/2018/01/09/java8%20Optional.1/
https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/