java 8 特性学习笔记

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()

猜你喜欢

转载自blog.csdn.net/qq_35212825/article/details/81068609