Lambda表达式

  • Lambda语法

    JDK8开始支持Lambda表达式,用来让程序编写更优雅
    利用Lambda可以更简洁的实现匿名内部类函数声明与调用
    基于Lambda提供stream流式处理极大简化对集合的操作

    1
    2
    3
    4
    5
    // Lambda表达式简化代码
    List<String> list = Arrays.asList("Cfa","Dsadsa","Adahhd","Adsads");
    // JDK1.8后List类新增sort()方法,和Collections类中的sort()方法一致
    // JDK1.8之后,Collections.sort()方法也是调用的List.sort()方法
    list.sort((a, b) -> a.compareTo(b));
    • 语法

      (参数列表) -> 实现语句

      参数列表:使用逗号分隔参数,参数类型可省略,单参数括号可省略。

      实现语句:单行直接写,多行用{}包括。

      约束条件:Lambda表达式只能实现有且只有一个抽象方法的接口,Java称为”函数式接口“。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      // 标准Lambda使用方式
      MathOperation add = (Integer a, Integer b) -> {
      System.out.println("加法运算:"+a + "+" + b);
      return a + b + 0f;
      };
      float operate = add.operate(1, 3);
      System.out.println("运算结果:"+operate);

      // 允许忽略参数类型
      MathOperation sub = (a, b) -> {
      System.out.println("减法运算:"+a+"-"+b);
      return a - b + 0f;
      };
      System.out.println("运算结果:"+sub.operate(5, 3));

      // 单行实现可以省略大括号和return关键字
      MathOperation mult = (a , b) -> a * b + 0f;
      System.out.println("运算结果:"+mult.operate(3, 5));
  • 函数式编程

    函数式编程是基于函数式接口并使用lambda表达的编程方式。
    函数式编程理念是将代码作为可重用数据代入到程序运行中。
    函数式编程强调”你想做什么”,而不是“你想怎么做” 。

    JDK1.8后提供了一系列新的函数式接口,位于java.util.function包下

    • 例子(Predicate函数式接口)

      函数式接口Predicate,用于测试传入的数据是否满足判断要求,实现test()方法进行逻辑判断。

      1
      2
      Predicate<Integer> predicate = a->a>4;
      System.out.println(predicate.test(5));
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      // 通过函数式编程获取list数组中满足条件的数据
      public static void main(String[] args) {
      List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
      // 获取List数组中偶数
      PredicateSample.filter(list, a->a%2==0);
      // 获取List数组中奇数
      PredicateSample.filter(list, a->a%2==1);
      // 获取List数组中大于5的偶数
      PredicateSample.filter(list, a->a>5 && a%2==0);
      }

      public static void filter(List<Integer> list, Predicate<Integer> predicate) {
      for (Integer num : list) {
      if (predicate.test(num)) {
      System.out.println(num);
      }
      }
      }
    • JDK8中常用函数式接口

      JDK8中常用函数式接口

      Function函数式接口使用

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      /**
      * 利用Function返回一个随机定长字符串
      * 通常用于加密、解密操作
      */
      public class FunctionSample {
      public static void main(String[] args) {
      // 定义一个小写数字字符串
      String chars = "abcdefghijklmnopqrstuvwxyz0123456789";
      // 定义一个StringBuffer用于存储生成的随机定长字符串
      StringBuffer sb = new StringBuffer();
      // 定义一个Random用于生成随机数
      Random random = new Random();
      Function<Integer, String> function = l->{
      // 循环返回的字符串长度l
      for (int i = 0; i < l; i++) {
      // 生成一个随机字符串的位置参数i1(随机数范围为chars的长度)
      int i1 = random.nextInt(chars.length());
      // 将该字符追加到StringBuffer数组中
      sb.append(chars.charAt(i1));
      }
      return sb.toString();
      };
      String apply = function.apply(8);
      System.out.println(apply);
      }
      }
    • 函数式注解

      @FunctionnalInterface:通知编译器这是函数式接口,进行抽象方法检查。

      函数式变成与面向对象变成比较

      函数式变成与面向对象变成比较

  • Stream流式处理

    Stream流式处理是建立在Lambda基础上的多数据处理技术。
    Stream对集合数据处理进行高度抽象,极大简化代码量。
    Stream可对集合进行迭代,去重,筛选,排序,聚合等一系列处理。

    1
    2
    3
    4
    5
    6
    // 获取List集合中最大的偶数
    Optional<Integer> op = Arrays.asList(1,2,3,4,5,6).stream()
    .filter(x->x%2==0)
    .sorted((a,b)->b-a)
    .findFirst();
    System.out.println(op.get());

    Stream常用方法

    Stream常用方法

    • 基于数组创建

      1
      2
      3
      String[] arr = {"A","B","C","D"};
      Stream<String> arr1 = Stream.of(arr);
      arr1.forEach(s-> System.out.println(s));
    • 基于集合创建

      1
      2
      List<String> list = Arrays.asList("A","B","C","D");
      list.stream().forEach(s-> System.out.println(s));
    • 基于generate方法创建无限长度流

      1
      2
      Stream<Integer> generate = Stream.generate(() -> new Random().nextInt(10));
      generate.limit(5).forEach(i-> System.out.println(i));
    • 基于迭代器创建流

      1
      2
      Stream<Integer> iterate = Stream.iterate(2, i -> i + 1);
      iterate.limit(5).forEach(i-> System.out.println(i));
    • 基于字符序列创建流

      1
      2
      3
      String s = "abdsad我的";
      IntStream chars = s.chars();
      chars.forEach(c-> System.out.println((char)c));
    • 案例1:提取集合中所有奇数并求和

      1
      2
      3
      4
      List<String> list = Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9");
      // mapToInt将流中每一个数据转为整数
      int sum = list.stream().mapToInt(s -> Integer.parseInt(s)).filter(i -> i % 2 == 1).sum();
      System.out.println(sum);
    • 案例2:所有名字首字母大写

      1
      2
      3
      List<String> list = Arrays.asList("tom", "lili", "whale", "shanshan");
      List<String> collect = list.stream().map(s -> s.substring(0, 1).toUpperCase() + s.substring(1)).collect(Collectors.toList());
      System.out.println(collect);
    • 案例3:将所有奇数从大到小排序,且不允许出现重复

      1
      2
      3
      4
      List<Integer> list = Arrays.asList(1,3,2,4,8,2,1,32,5,7,0,9);
      // distinct()去除重复流数据
      List<Integer> sorted = list.stream().distinct().filter(s -> s % 2 == 1).sorted((a, b) -> b - a).collect(Collectors.toList());
      System.out.println(sorted);