Lambda表达式:
参数 + 箭头 + 主体
使用方法:
new Thread(() ->{
//TODO:
}).start();
Predicate<OrderVO> STATUS = e -> {
if (e == null) {
return false;
}else {
return true;
}
};
- 这里涉及到三个函数:
Predicate<T> T为输入参数类型(e),返回为Boolean值
test() 返回true|false,通常用来判断某个值是否为某个固定值
举个栗子:
Predicate<OrderVO> PREDICATE = e -> {
if(e.getNum() > 10) return true;
else return false;
};
boolean parse = PREDICATE.test(list.get(0));
Function<T,R> T为输入参数类型,R为返回参数类型
apply方法接收一个模板作为输入参数,实例化Function时需要实现该方法
Function<T, V> andThen(Function<? super R, ? extends V> after) 将多个Function的apply方法调用连接起来。function1.andThen(function2).apply("hello"); function1先调用,function2后调用。
Function<V, R> compose(Function<? super V, ? extends T> before)类似于andThen,但function2先调用function1后调用。
Consumer<T> T为输入参数类型
通过传递一个参数来对参数进行操作。
方法调用:
目标引用::方法名称
如果lambda表达式只是调用一个特定的已经存在的方法,则可以使用方法引用。
使用“::”操作符将方法名和对象或类的名字分隔开来。以下是四种使用情况:
对象::实例方法;类::静态方法;类::实例方法;类::new
流:java.util.stream.Stream
中间操作方法:
filter:接受一个返回boolean的lambda表达式的参数,返回由流元素组成的流,对数据进行筛选。
举个栗子:list.stream().filter(e ->e.getNum > 300)
distinct:返回不同对象组成的流,内部使用对象的equals方法比较是否相同,返回不重复的对象。
举个栗子:list.stream().distinct()
skip:从第几条数据开始筛选。接受long参数,返回剩下元素的流,如果总元素比n小,返回空流。
limit:返回条数,接收long类型maxSize
sorted:排序,接收Comparator参数。
举个栗子:
list.stream().sorted((a,b) -> a.getNum() - b.getNum())
可以简化为list.stream().sorted(Comparator.comparingInt(OrderVO::getNum) )
map:提取流中的元素。
终止操作方法:
anyMatch:判断流中是否有一个元素能匹配给定的谓词。参数:Predicate
举个栗子:boolean state = list.stream().skip(0).anyMatch(e-> e.getNum()>20);
allMatch:判断流中元素是否全部匹配。
noneMatch:判断流中是否全部不匹配。跟allMatch相反
findFirst:找到第一个元素
findAny:返回当前流中的任意元素。
举个栗子:list.stream().findAny(); 然鹅,此时发现返回的永远是流中的第一个元素,那么这和findFirst方法又有什么区别呢,怎么体现它的any的??存疑,继续往下学习。
forEach:遍历流中的每个元素。
举个栗子:list.stream().forEach(e -> e.setDate("2018-07-12"));
collect:将结果返回为一个特定的格式。
举个栗子:
reduce:聚合操作,返回单个结果值,实现average,sum,min,max,count
T reduce(T identity, BinaryOperator<T> accumulator);
identity:计算初始值,accumulator:计算的累加器(方法第一个参数为上次计算结果,第二个参数为stream中的元素)
举个栗子:int all = list.stream().map(OrderVO::getNum).reduce(10, (sum,item) -> sum + item);
count
并行流:
并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。
list.stream().parallel()或者list.parallelStream()就可以将集合转换为并行流。
在并行流中使用findAny可以获取任意的元素。
并行流也涉及多线程安全问题,也需要保证线程安全。
流的创建:
1. Stream.of("2018","2017","2016","2015");
Stream.empty()得到一个空流。
2. int[] numbers = {1,2,3,4,5,6,7,8}; 通过Arrays.stream(numbers)获取流
3. list.stream() 通过集合创建流
4. 通过文件生成流:File.lines(Paths.get(uri),Charset.defaultCharset())
默认方法和静态方法:
public interface Person {
//默认方法
default String getName(String name) {
return name;
}
}
public class Student implements Person {
}
public class Test {
public static void main(String[] args) {
Person p = new Student();
String name = p.getName("小李");
System.out.println(name);
}
}
考虑如果接口中定义了一个默认方法,而另外一个父类或者接口中又定义了一个同名的方法,该选择哪个?
1. 选择父类中的接口。如果一个父类提供了具体的实现方法,那么接口中具有相同名称和参数的默认方法会被忽略。
2. 接口冲突。如果一个父接口提供了一个默认方法,而另一个接口也提供了具有相同名称和参数类型的方法(不管该方法是否是默认方法),那么必须通过覆盖方法来解决。
记住一个原则,就是“类优先”,即当类和接口都有一个同名方法时,只有父类中的方法会起作用。
CompletableFuture:
构建异步应用。
先看看Future。Future应用背景是某个方法计算过程非常耗时,等待其响应显然不明智,可在调用方法的时候立马返回一个Future,通过Future去控制方法的计算过程。
Future方法:
get():获取计算结果(如果没有计算完,必须等待)
cancel():还未计算完可取消计算。(是否会回滚?)
isDone():判断是否计算完
isCancelled():判断是否计算被取消
Future提供了异步执行任务的能力,但是对于结果的获取不方便,只能通过阻塞或是轮询的方式得到任务结果。但是阻塞的方法与传统意义上的异步编程是相违背的,轮询又会消耗无谓的CPU资源。因此java8里新增了一个类CompletableFuture。
CompletableFuture也可以通过阻塞和轮询的方式获取结果(不推荐)
getNow方法:如果计算完则返回结果或抛出异常,否则返回给定的valueIfAbsent的值。
创建CompletableFuture对象:
CompletableFuture.completedFuture返回一个已经计算好的CompletableFuture。
下面四个静态方法用来为一段异步执行的代码创建CompletableFuture对象:
以Async结尾并且没有指定Executor的方法会使用ForkJoinPool.commonPool()作为线程池执行异步代码。这些方法的参数都是函数式接口。所以:
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
//TODO:计算
return "";
});
CompletableFuture计算结果完成时,可以执行特定的Action,主要是下面的方法:
public CompletableFuture<T> whenComplete(BiConsumer<? super T,? super Throwable> action)
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action)
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action, Executor executor)
public CompletableFuture<T> exceptionally(Function<Throwable,? extends T> fn)
这些方法中,不以Async结尾的,会使用相同的线程执行,否则会使用其他线程执行。
exceptionally方法会返回一个新的CompletableFuture,当原始CompletableFuture抛出异常时触发
~~~~~~~~~~~~~~~
thenApply 对数据进行一些处理或变换
thenAccept 纯消费,不返回新的计算值
thenRun 对上一步计算结果不关心,执行下一操作
applyToEither 两个CompletionStage,谁计算的快就使用哪个结果进行下一步转换
举个栗子:String result = CompletableFuture.supplyAsync(() -> {
return "1";
}).applyToEither(CompletableFuture.supplyAsync(() -> {
return "2";
}), s -> s).join();
LocalDate,LocalTime:
LocalDate不可变的对象,只提供最简单的日期。
可以使用TemporalField接口得到对应枚举的值,ChronoField枚举类实现了此接口:
举个栗子:localDate.get(ChronoField.YEAR);//ChronoField.MONTH_OF_YEAR,ChronoField.DAY_OF_MONTH
日期加时间:LocalDateTime
可以得到:2018-07-16T16:29:34.553
时间戳:System.currentTimeMillis()