目录:java
1、简介程序员
2、函数接口编程
3、Lambda表达式api
4、目标类型数组
5、流闭包
6、function包并发
7、对并发的影响app
正文函数式编程
1、简介函数
一、java中lambda的由来
开发类库的程序员使用java时,发现抽象级别还不够,尤为是面对大型数据集合时,java还欠缺高效的并行操做。为了编写这类处理批量数据的并行类库,就须要在为java增长lambda表达式。
再如,当咱们定义一个线程类时,能够将该类实现Runnable接口(该接口只有一个方法run()),并实现run方法便可。但大多数状况下咱们可能并不这么作,由于该线程可能只会被使用一次,此时咱们通常会使用匿名内部类将线程的行为进行内联,代码举例以下:
可是匿名内部类存在缺陷:
等等,因为上述缺陷,须要借助函数式编程得以解决。
2、函数式接口
咱们对面向对象编程并不陌生,面向对象编程是对数据进行抽象,而函数式编程是对行为进行抽象。现实世界中,数据和行为是并存的。
那么什么是函数式编程呢?其核心思想是:在思考问题时,使用不可变值和函数,函数对一个值进行处理,映射成另外一个值。
函数式接口定义:把只有一个抽象方法的接口称为函数式接口,可用作lambda表达式的类型。java中的函数式接口如Runnable、Comparator、Callable等。
如何自定义一个函数式接口?其实咱们并须要额外的工做来声明一个接口是函数式接口,编译器会根据接口的结构自行判断,固然并不是简单对接口中的方法进行计数。另外,java api提供了@FunctionalInterface注解来显示声明一个接口为函数式接口,加上该注解后,编译器就会验证该接口是否知足函数式接口的要求。
java8中增长了一个新的package:java.util.function,里面包含了经常使用的函数式接口。
3、Lambda表达式
lambda表达式又被称为闭包或匿名方法。
下面对lambda进行一些简单举例:
因而可知,lambda表达式由参数列表、箭头符号(->)和函数体组成,其中函数体既能够是一个表达式,也能够是一个语句块。表达式函数体适用于小型lambda表达式,它省略了return关键字,使语法更简洁。
在使用lambda表达式时,能够显示声明参数的类型,如:(int x, int y) -> x + y,其实也能够省略参数类型,让编译器本身去推导出来,如:(x, y) -> x + y。
4、目标类型
一、目标类型
编译器负责推导lambda表达式的类型,它利用lambda表达式所在上下文所期待的类型进行推导,这个被期待的类型就是目标类型。lambda只能出如今目标类型为函数接口的上下文中。
lambda表达式对目标类型也是有要求的,当下面全部条件都成立时,lambda表达式才会赋给目标类型T。
二、目标类型的上下文包括:
三、词法做用域
lambda引用的是值,而不是变量。在匿名内部类中引用它所在方法的变量时,该变量必须声明为final,虽然Java8中放宽了此限制,能够引用非final变量,可是该变量在既成事实上必须是final的,即不能再匿名内部类中改变它所在方法的变量值,不然编译器会报错。既成事实上的final是指只能给该变量赋值一次,换句话说,Lambda引用的是值,而不是变量。举例以下:
上面两个例子中,只要在内部类或lambda表达式中修改其所在方法中的变量都会报错。lambda表达式不支持修改外部变量的另外一个缘由是:咱们可使用更好的方式实现相同的效果:使用规约。java.util.function包中提供了各类规约,如sum、min、max等。
在内部类中定义和外部类中相同的变量时,其内部类中定义的变量会覆盖外部类中定义的变量。而lambda表达式基于词法做用域,在lambda函数体里面不容许定义和外面相同的变量,若是定义则会报错。举例:
所以,能够说:lambda表达式对值封闭,对变量开放。
5、流
一、概念
外部迭代:经过Iterator的方式进行迭代的过程称为外部迭代。
内部迭代:经过stream的方式进行迭代的过程称为内部迭代。
流 - Stream:是用函数式编程的方式在集合类上进行复杂操做的工具。java8中为集合类和数组都提供了转为Stream的方法,由集合或数组生成的Stream不是一个新集合,而是建立新集合的配方。
惰性求值方法:只描述或刻画Stream,最终不产生新集合的方法叫惰性求值方法,如Stream的filter方法。
及早求值方法:最终会生成新集合的方法叫及早求值方法,如Stream的count方法。
说明:判断一个方法是惰性求值仍是及早求值很简单:只需看它的返回值,若是返回值是Stream,那么就是惰性求值方法,若是返回的是另外一个值或空,就是及早求值方法。使用这些操做的理想方式就是造成一个惰性求值的链,最后用一个及早求值的操做返回想要的结果。
二、经常使用的流操做
2.1 collect(Collector<? super T,A,R>)
做用:该方法由Stream里的值生成一个列表,是一个及早求值方法。
举例:
List<String> list = Stream.of("a", "1", "b", "2").collect(Collectors.toList());
2.2 Stream<R> map(Function<? super T, ? super R>)
做用:将一个流中的值转换成一个新流,是一个惰性求值方法。
举例:
Stream<String> stream = Stream.of("a","b","c").map(one -> one.toUpperCase());
2.3 Stream<T> filter(Predicate<? super T>)
做用:遍历流中的数据并根据条件进行过滤,造成一个新流,是一个惰性求值方法。
举例:
Stream<String> stream1 = Stream.of("abc","bcd","def").filter(one -> one.contains("bc"));
2.4 Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>>)
做用:当流中包含多个列表时,可将这多个列表中的内容打平放到一个列表下的流中,是一个惰性求值方法。
举例:
Stream<String> stream2 = Stream.of(Arrays.asList("a","b","c"), Arrays.asList("abc","bcd","def")).flatMap(one -> one.stream());
2.5 Optional<T> max(Comparator<? super T>)和Optional<T> min(Comparator<? super T>)
做用:获取一个集合中的最大值和最小值,是两个及早求值方法
举例:
Integer max = Stream.of(1,2,3).max(Comparator.comparing(one->one)).get();
Integer min = Stream.of(1,2,3).min(Comparator.comparing(one->one)).get();
2.6 long count()
做用:返回Stream中元素的数量,是一个及早求值方法
举例:
Long count = Stream.of(1,2,3).count();
2.7 Optional<T> reduce(BinaryOperator<T>)
做用:从stream的一组值中生成1个值,count、max、min都属于reduce操做,是一个及早求值方法。
举例:第1个参数one是上次函数计算的返回值,其初始值是stream中第1个值;第2个参数two是stream中的元素值,其初始值是stream中第2个值,返回类型是Optional,经过get方法获取其值
Integer count = Stream.of(1,2,3,4,5,6).reduce((one, two) -> { System.out.println(one + ":"+two);return two; }).get();
2.8 T reduce(T, BinaryOperator<T>)
举例:该方法比上一个方法多了一个初始值100,one仍然表明上次函数计算的返回值,其初始值为就是设定的初始值100;two仍然是stream中的元素值,其初始值是stream中的第1个值。因为该方法指定了初始值,所以该方法的返回值类型就是设定的初始值类型,即Integer。
Integer count1 = Stream.of(1,2,3,4,5,6).reduce(100, (one, two) -> { System.out.println(one + ":"+two);return two; });
2.9 Stream<T> distinct()
做用:返回由该流的不一样元素组成的一个新流,是一个惰性求值方法
举例:
Stream.of(3,2,5,3,4,3).distinct().peek(one -> System.out.println(one)).count();
2.10 Stream<T> limit(int maxSize)
做用:返回前maxSize个元素组成的新流,是一个惰性求值方法
举例:
System.out.println(Stream.of(1,2,3,4,5,6).limit(3).filter(one -> {System.out.println(one);return true;}).count());
2.11 Stream<T> peek(Consumer<? super T>)
做用:返回一个由该流的元素组成的新流,而且对新流中每一个元素执行指定的操做
举例:
Stream stream = Stream.of(1,2,3,4,5,6).peek(one -> System.out.println(one));
2.12 Stream<T> skip(long n)
做用:从流的第1个元素开始,跳过n个元素,把从第n+1个元素开始到最后全部的元素造成一个新流
举例:
Stream.of(1,2,3,4,5,6).skip(3).peek(one -> System.out.println(one)).count();
2.13 Stream<T> sorted()
做用:将流中的元素按照天然顺序进行排序,是一个惰性求值方法
举例:
Stream.of(6,2,5,3,4,1).peek(one-> System.out.println(one)).sorted().peek(one-> System.out.println(one)).count();
2.14 boolean allMatch(Predicate<? super T>)
做用:返回流中的全部元素是否都与条件匹配
举例:
System.out.println(Stream.of(6,2,5,3,4,1).allMatch(one -> one>3));
2.15 boolean anyMatch(Predicate<? super T>)
做用:返回流中是否存在与条件匹配的元素
举例:
System.out.println(Stream.of(6,2,5,3,4,1).anyMatch(one -> one>3));
2.16 boolean noneMatch(Predicate<? super T>)
做用:返回流中全部元素是否都不与条件匹配
举例:
System.out.println(Stream.of(6,2,5,3,4,1).noneMatch(one -> one>3));
2.17 findAny()
做用:返回描述流的一些元素的Optional对象,若是流为空,则返回一个空Optional
举例:
System.out.println(Stream.of(3,2,5,6,4,1).findAny().get());
2.18 findFirst()
做用:返回描述流的第一个元素的Optional对象,若是流为空,则返回一个空Optional
举例:
System.out.println(Stream.of(3,2,5,6,4,1).findAny().get());
2.19 void forEach(Consumer<? super T>)
做用:对流中每一个元素循环进行操做
举例:
Stream.of(3,2,5,6,4,1).forEach(one -> System.out.println(one));
2.20 Object[] toArray()
做用:返回一个包含流中元素的数组
举例:
Integer[] values = (Integer[])Stream.of(3,2,5,6,4,1).toArray();
6、function包
一、Predicate<T>
抽象方法为boolean test(T),传入T类型的参数,返回一个boolean类型值。可用于流中数值判断。
举例:
Predicate<String> predicate = one -> one.length() > 0;
二、Consumer<T>
抽象方法为void accept(T),传入T类型的参数,不返回值。可用于实现消费者
举例:
Consumer<Integer> consumer = one -> System.out.println(one);
三、Supplier<T>
抽象方法为String[] value(),无参数,返回一个字符串数组。可用于实现生产者
举例:
Supplier<Integer> supplier = () -> new Integer(100);
四、Function<T, R>
抽象方法为R apply(T),传入参数T,返回结果R。
举例:
Function<String, Integer> function = one -> one.length();
五、UnaryOperator<T>
抽象方法T apply(T),接收T对象,返回T对象。
举例:
UnaryOperator<String> unaryOperator = one -> "hello:" + one;
六、BinaryOperator<T>
抽象方法为T apply(T, T),接收2个T对象,返回T对象。
举例:
BinaryOperator<Integer> binaryOperator = (one, two) -> one + two;
7、对并发的影响
待续