关于Java8的精心总结( 二 )

?
//内部迭代integerList.forEach(new Consumer<Integer>() {//匿名内部类@Overridepublic void accept(Integer integer) {System.out.println(integer);}});二、函数式(Functional)接口? 函数式接口是可以通过三种方式实现的:Lambda表达式、方法引用、构造器引用
通过Lambda表达式、方法引用或者构造器引用的来创建一个函数式接口的实例
关于函数式接口:

  1. 如果一个接口只有一个抽象方法 , 那么该接口就是一个函数式接口
  2. 如果我们在某个接口上声明了@FunctionalInterface注解 , 那么编译器就会按照函数式接口的定义来要求该接口 。
  3. 如果一个接口只有一个抽象方法 , 但是在该接口上并没有声明@FunctionalInterface注解 , 那么编译器依旧会把该接口看作一个函数式接口
Java8里面引入的很多函数式接口它们都位于java.util.function下面 。
以下是一些常用的函数式接口:
位于java.util.function这个包下面
Consumer消费者 接受一个参数 , 不返回结果
public interface Consumer { void accept(T t); }
Function , 接受一个参数 , 返回一个结果
public interface Function { R Apply(T t); }
BiFunction接收两个参数 , 返回一个结果(其中BI是bidirectional的缩写 , 意思是双向)
public interface BiFunction { R apply(T t, U u); }
Supplier 提供者 , 供应者 , 不接收任何参数 , 返回一个结果
public interface Supplier { T get(); }
Predicate谓语 , 接收一个参数 , 返回一个布尔值(根据给定的参数 , 返回布尔)
public interface Predicate { boolean test(T t); }
三、方法引用方法引用是Lambda表达式的一种特殊情况(或者说是Lambda表达式的一个语法糖) , 可以理解为方法引用和Lambda表达式这两种方式所实现的功能其实一样的 , 完全等价 , 但是方法引用的方式更简洁 。
我们可以将方法引用看作是一个函数指针(Function pointer)
方法引用(method references):
List<Integer> integerList = Arrays.asList(1,2,3,4,5); //方法引用的方式 integerList.forEach(System.out::println);方法引用有4种:
1、类名::静态方法名
以下这两种形式是完全不等价的
classname::staticmethod(表示的是指向 , 函数指针的概念)
classname.staticmethod(真正表示的是方法调用的概念)
2、引用名(对象名)::实例方法名
3、类名::实例方法名
4、构造方法引用(constructor references):类名::new
四、强大的Stream API【关于Java8的精心总结】其实就是JDK8提供给我们新的API , 经常和Lambda表达式和函数式接口一起使用
分为串行流和并行流
list.stream()串行流 , 只有一个线程 , 一个线程执行所有操作
list.parallelStream()并行流 , 多线程 , 分工合作
list.stream().map():map此处的意思是映射的意思
Stream也是一个接口 , 里面的绝大多数方法都是高阶函数
Stream流 , 他是与Lambda表达式相伴相生的 , 通过流的方式我们可以更好的操作集合
流的三部分构成:(SQL语句和流非常非常像)
1、源
2、零个或若干个中间操作(操作的是这个源 , 操作值的是过滤 , 排序 , 映射 , 分区等 , 这些操作本身有点像SQL语句)
3、终止操作
流操作分类:
1、惰性求值
2、及早求值
流的所有的中间操作方法都是lazy的(或者说是延迟的 , 或者说是惰性求值的) , 在没有遇到终止操作或者及早求值的操作的情况下 , 中间操作是不会被执行的 , 只有在遇到终止操作的时候 , 这若干个中间操作才会一并的执行
stream().xxx().zzz().count();filter()用来判断里面的条件是真还是假?如果是假 , 就从流当中过滤掉;如果是真 , 就继续放到流当中 , 供后续操作使用
流: