JAVA8新特性
Lambda表达式
1.基本格式
(参数列表)->{代码}
2.省略规则
- 参数类型可以省略
- 方法体只有一句代码时大括号return和唯一一句代码的分号可以省略
- 方法只有一个参数时小括号可以省略
Stream流
1.创建流
-
单列集合:集合对象.stream()
-
数组:Arrays.stream(数组对象) 或 Stream.of(数组对象)
-
双列集合:转换成单列集合后再创建
例:
Map<String,Integer> map = new HashMap<>(); Stream<Map.Entry<String,Integer>> stream = map.entrySet().stream();
2.中间操作
-
filter
可以对流中数据进行过滤,符合条件的才能留在流中
-
map
可以把对流中的元素进行计算或转换
-
distinct
可以去除流中的重复元素
-
sorted
可以对流中的元素进行排序
注意:如果调用空参的sorted()方法,需要流中的元素实现了Comparable
-
limit
可以设置流的最大长度,超出的部分将被抛弃
-
skip
跳过流中的前n个元素,返回剩下的元素
-
flatMap
map只能把一个对象转换成另一个对象来作为流中的元素。而flatMap可以把一个对象转换成多个对象作为流中的元素
3.终结操作
-
forEach
对流中的元素进行遍历操作,可以通过传入的参数去指定对遍历到的元素进行什么具体操作
-
count
可以用来获取当前流中元素的个数
-
max & min
可以用来计算流中的最值
-
collect
把当前流转换成一个
-
anyMatch
可以用来判断是否有任意符合匹配条件的元素,结果为Boolean
-
allMatch
可以用来判断是否都符合匹配条件,结果为Boolean
-
noneMatch
可以判断是否都不符合匹配条件,结果为Boolean
-
findAny
获取流中的任意一个元素,该方法没有办法保证获取的一定是流中的第一个元素
-
findFirst
获取流中的第一个元素
-
reduce归并
对流中的数据按照自定义的计算方式计算出一个结果。(缩减操作)
reduce的作用是把stream中的元素给组合起来,我们可以传入一个初始值,它会按照我们的计算方式依次拿流中的元素和在初始化值的基础上进行计算,计算结果再和后面的元素计算
内部的计算方式如下
T result = identity; for (T element : this stream) result = accumulator.apply(result,element) return result;
4.注意事项
- 惰性求值 (如果没有终结操作,没有中间操作是不会得到执行的)
- 流是一次性的(一旦一个流对象经过一个终结操作后,这个流就不能再被使用)
- 不会影响原数据 (我们在流中可以多数据做很多处理,但正常情况下是不会影响原来集合中的元素的。这往往也是我们期望的)
Optional
1.创建对象
一般使用Optional的静态方法ofNullable来把数据封装成一个Optional对象,无论传入的参数是否为null都不会出现问题
Example example = getExample();
Optional<Example> exampleOptional = Optional.ofNullable(example);
在确定一个对象不为空的则可以使用Optional的静态方法of来把数据封装成Optional对象
Example example = getExample();
Optional<Example> exampleOptional = Optional.of(example);
如果一个方法的返回值类型是Optional类型,而如果我们经判断发现某次得到的返回值为null,这个时候就需要把null封装成Optional对象返回。这时则可以使用Optional的静态方法empty来进行封装。
Optional.empty();
2.消费值
使用 ifPresent 方法来消费其中的值 ,这个方法会判断其内封装的数据是否为空,不为空时才会执行具体的消费代码
optiona1<Example> exampleOptiona1 = optional.ofNul1ab1e(getAxample());
exampleOptiona1.ifPresent(example -> system.out.println(example.getName()));
3.获取值
-
get()
不推荐使用此种方法获取,因为当Optional内部数据为空时会出现异常
-
orElseGet()
获取数据并且设置数据为空时的黑认值 。如果数据不为空就能获取到该数据 。如果为空则根据你传入的参数来创建对象作为默认值返回
Optional<Example> exampleOptional = Optional.ofNullable(getExample()); Example example = exampleOptional.orElseGet(() -> new Example());
-
orElseThrow()
获取数据,如果数据不为空就能获取到该数据,如果为空则根据传入的参数来创建异常抛出
Optional<Example> exampleOptional = Optional.ofNullable(getExample()); try{ Example example = exampleOptional.orElseThrow(() -> new RuntimeException("example为空")); System.out.println(example.getName()); } catch(Throwable throwable) { throwable.printStachTrace(); }
4.过滤
使用filter方法对数据进行过滤,如果原本是有数据的,但是不符合判断,也会变成一个无数据的Optional对象
Optional<Example> exampleOptional = Optional.ofNullable(getExample());
exampleOptional.filter(example -> example.getAge() > 100).ifPresent(example -> System.out.println(example.getName()));
5.判断
可以使用isPresent方法进行是否存在数据的判断。如果为空,返回值为false;如果不为空,返回值为true。但是这种方式并不能体现Optional的好处,更推荐使用ifPresent方法。
optiona1<Example> exampleOptional = optional.ofNullab1e(getExample());
if (exampleOptional.isPresent() {
system.out.println(exampleOptional.get().getName());
}
6.数据转换
Optional还提供了map可以让我们的对数据进行转换,并且转换得到的数据也还是被Optional包装好的,保证了我们的使用安全。
optiona1<Example> exampleOptional = optional.ofNullab1e(getExample());
Optional<List<Book>> books = exampleOptional.map(author -> author.getBooks());
books.ifPresent(book -> System.out.printLn(book.getName()));
函数式接口
1.概述
只有一个抽象方法的接口我们称之为函数接口
JDK的函数式接口都加上了 @FunctionalINterface 注解进行标识。但是无论是否加上该注解只要接口中只有一个抽象方法,都是函数式接口
2.常见函数式接口
-
Consumer 消费接口
可以在方法中对传入的参数进行消费
-
Function 计算转换接口
可以在方法中对传入的参数计算或转换,把结果返回
-
Predicate 判断接口
可以在方法中对传入的参数条件判断,返回判断结果
-
Supplier 生产型接口
可以在方法中创建对象,把创建好的对象返回
3.常用的默认方法
-
and
在使用 Predicate 接口的时候可能需要进行判断条件的拼接。而 and方法相当于是使用 && 来拼接两个判断条件
-
or
在使用 Predicate 接口时相当于 ||
-
negete
Predicate 接口中的方法,相当于是在判断前加了 ! 表示取反
方法引用
在使用Lambda时,如果方法体中只有一个方法的调用的话(包括构造方法),可以用方法引用进一步简化代码
基本格式:
类名或对象名::方法名
高级用法
JDK5中引入的自动装箱和自动拆箱虽然方便,但也是要消耗时间的,为了能对这部分的时间消耗进行优化,Stream提供了很多专门针对基本数据类型的方法
例如:
mapToInt、mapToLong、mapToDouble、flatMapToInt、flatMapToDouble 等
并行流
当流中有大量元素时,可以使用并行流去提高操作的效率。其实并行流就是把任务分配给多个线程去完成。使用Stream时,只需要修改一个方法的调用就可以使用并行流,从而提高效率。
stream.parallel()
也可以通过 parallelStream 直接获取并行流对象
parallelStream()