美文网首页
java8 lambda

java8 lambda

作者: itsenlin | 来源:发表于2018-05-13 17:53 被阅读0次

定义

“Lambda 表达式”(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。

java8增加了对函数式编程的支撑,即java8 lambda表达式。通过lambda表达式可以方便程序员将代码作为数据进行传递,可以赋值给一个变量也可以作为函数参数、返回值来使用,类似于java的匿名内部类。

入门例子

当前开发使用最多的就是多线程,

  • 在java中一般是通过实现Runnable接口,如下
    new Thread(new Runnable() {
      @Override
      public void run() {
      System.out.println("Hello world!");
      }
    }).start();
    
  • 在java8中可以使用lambda表达式形式,更简单,如下
    new Thread( () -> System.out.println("Hello world!") ).start();
    

java8 lambda语法

  • 基本语法
    (parameters) -> expression

    (parameters) ->{ statements; }

说明:parameters可以带参数类型也可以省略参数类型,但省略参数类型时必须能保证jdk自动推断

  • 函数接口

函数接口是只有一个抽象方法的接口,用作Lambda表达式的类型,可以使用@FunctionalInterface注解标注。接口中单一方法的命令并不重要,只要方法签名和Lambda表达式的类型匹配。

  • JDK中默认提供的函数接口
接口 参数 返回类型 示例
Predicate<T> T boolean 判断结果的真假,是与否等
Consumer<T> T void 输出一个值,像上面线程
Function<T,R> T R 获得一个对象的名字
Supplier<T> None T 工厂方法
UnaryOperator<T> T T 逻辑非(!)
BinaryOperator<T> (T,T) T 求两个数的乘积(*)

java8 Stream

java8 不仅在语言层面支持了lambda表达式,还为此对类库做了改进,包括集合类的API以及引入的流(Stream),Stream很多方法的参数都是lambda表达式。

  • 内部迭代和外部迭代
    相对于集合代码来说的,像常用的for/while循环通过产生新的Iterator对象来控制整个迭代过程,就是外部迭代。而java8中集合对你的stream()方法直接是使用Stream对集合中的数据进行迭代,就是内部代码。

          List<String> list = new ArrayList<>();
          list.add("hello");
          list.add("world");
          list.add("!");
    
          //外部迭代
          for (String s : list) {
              System.out.println(s);
          }
    
          //内部迭代
          list.stream().forEach(e -> System.out.println(e));
    
  • 惰性求值
    在Stream的操作中,有一些像filter方法只描述Stream,并不会产生一个新的集合的方法,叫做惰性求值方法;就像医生开的药方,并不是具体的药品。

  • 及早求值
    在Stream的操作中,还有一类像count这种方法最终会从Stream中产生最终值,叫做及早求值方法;这个已经是根据药方获取到相应药品了。

判断惰性求值还是及早求值很简单:返回Stream对象就是惰性求值;返回另外类型的值或者空,则是及早求值。
对Stream最理想的操作是形成一个惰性求值链,最后用一个及早求值的操作返回想要的结果。

        long num = list.stream().filter(s -> s.length() > 2).count();
        System.out.println("num: " + num);
----------------------------------------------------------
输出:num: 2

java8 常用的Stream操作

  • collect(toList())
    将一个流中的值生成一个列表,及早求值函数。是一个通用的结构。
List<String> list = Stream.of("hello", "world", "!").collect(Collectors.toList());
  • map
    如果一个函数可以将一种类型的值转换成另外一种类型,则map就可以使用此函数将一个流中的值转换成一个新的流。例如将字符串字符全大写
List<String> collect = Stream.of("hello", "world", "!").map(s -> s.toUpperCase()).collect(Collectors.toList());
collect.stream().forEach(s -> System.out.print(s + " "));
------------------------------------------------------
输出:HELLO WORLD ! 

map函数接收一个Function<T,R>类型的参数。

  • filter
    遍历数据并检查其中的元素是filer的本职工作。例子可以参考前面的。

filter函数增收一个Predicate<T>类型的参数

  • flatMap
    与map类似,可以将Stream中的值进行替换;与map不一样的是flatMap可以将多个Stream连接成一个Stream
List<String> together = Stream.of(asList("a", "b"), asList("c", "d")).flatMap(s -> s.stream()).collect(Collectors.toList());

与map一样接收一个Function<T,R>类型参数,不过R的类型限定为一个Stream类型。

  • max和min
    Stream上常用的操作之一是求最大或者最小值。这个要考虑的是用什么作为排序的指标,例如数值大小、字符串长度、字典序等等。
System.out.println("max: " + Stream.of(asList(1, 2), asList(3, 4)).flatMap(s -> s.stream()).max(Comparator.comparing(n -> n)).get());
System.out.println("min: " + Stream.of(asList(1, 2), asList(3, 4)).flatMap(s -> s.stream()).min(Comparator.comparing(n -> n)).get());
----------------------------------------------------------------------
输出:max: 4
      min: 1

接收一个Comparator对象,此类提供了一个静态函数comparing可以方便用户实现一个比较器。此函数参数、返回值都是lambda表达式。返回的是一个Optional对象(后面再专门讨论),需要使用get方法获取相应的值。

  • reduce
    实现从一组值中生成一个值。前面例子中的count、max、min方法就是reduce操作,只是已经纳入了标准库中了。使用reduce实现数字累加,如下
System.out.println("sum: " + Stream.of(1,2,3).reduce(0, (acc,elment) -> acc + elment));
------------------------------------
输出:sum: 6

reduce第1个参数是初始值,第二个参数叫reducer,是一个BinaryOperator类型的lambda表达式。

参考

《java 8函数式编程》
http://www.importnew.com/16436.html

相关文章

网友评论

      本文标题:java8 lambda

      本文链接:https://www.haomeiwen.com/subject/mvocdftx.html