什么是lambda表达式

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

    Lambda表达式语法格式

  • lambda operator ```java public interface MathOperation { public Float operate(Integer a, Integer b); } //(参数列表)->实现语句

public static void main(String[] args) { //1、标准使用方式 //约束条件:Lambda表达式只能实现有且只有一个抽象方法的接口,Java中成为函数式接口 MathOperation addition = (Integer a, Integer b) -> { System.out.println(“加法运算”); return a + b + 0f; }; System.out.println( addition.operate(5, 3)); //2、lambda允许忽略参数类型 MathOperation substraction = (a, b) -> { return Float.valueOf(a - b); }; System.out.println(substraction.operate(1111, (int) 11.1)); //3、单行实现代码可以省略大括号和return MathOperation multiplication = (a, b) -> Float.valueOf(a * b); System.out.println(multiplication.operate(3, 5)); }

  1. - 使用逗号分隔参数,参数类型可以省略,单参数括号可以省略
  2. - 单行直接写,多行用{}包括,并且要在最后一句使用return返回结果
  3. - 函数式接口:有且只有一个抽象方法的接口称为函数式接口,可以使用Lambda表达式快速的实现函数式接口;函数式接口和Lambda表达式两者加起来形成了函数式编程
  4. <a name="YCQyi"></a>
  5. ## 函数式编程
  6. - 函数式编程是基于函数式接口(有且只有一个抽象方法的接口称为函数式接口)并使用lambda表达的编程方式
  7. - 函数式编程理念是将代码作为可重用数据带入到程序运行中
  8. - 函数式编程强调“你想做什么”,而不是:“你想怎么做”
  9. - Java中拥有大量的函数式接口,如Java .lang.Runnable;JDK8后提供了一系列新的函数式接口,位于java.util.funcation
  10. - 函数式接口Predicate是新增的函数式接口,位于java.util.funcation;Predicate用于测试传入的数据是否满足判断要求;Predicate接口需要实现test()方法进行逻辑判断。
  11. ```java
  12. /**
  13. * 理解函数式编程
  14. * Predicate函数式接口的使用方法
  15. */
  16. public class PredicateSample {
  17. public static void main(String[] args) {
  18. Predicate<Integer> predicate = n -> n > 4;
  19. System.out.println(predicate.test(2));
  20. List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
  21. //函数式编程理念是将代码作为可重用数据带入到程序运行中
  22. filter(list, n -> n % 2 == 1); //获取所有奇数
  23. filter(list, n -> n % 2 == 0);// 获取所有偶数
  24. filter(list, n -> n > 5 && n % 2 == 0);//获取所有大于5的偶数
  25. /* for (Integer integer : list) {
  26. if (!(integer % 2 == 0)) {
  27. System.out.println("integer = " + integer);
  28. }
  29. }*/
  30. }
  31. public static void filter(List<Integer> list, Predicate<Integer> predicate) {
  32. for (Integer integer : list) {
  33. if (predicate.test(integer)) {
  34. System.out.println("integer = " + integer);
  35. }
  36. }
  37. }
  38. }
接口 用途
Cosumer 对应有一个输入参数无输出的功能代码
Function 对应一个有输入参数且需要返回数据的功能带代码,第一个参数说明参数的类型,第二个参数说明返回值类型
Predicate 用于条件判断,固定返回布尔值
  • Consumer函数式接口

    1. /**
    2. * Consumer接口的使用
    3. */
    4. public class ConsumerSimple {
    5. public static void main(String[] args) {
    6. output(n -> System.out.println(n));
    7. output(s -> {
    8. System.out.println("向XXX网站发送数据包" + s);
    9. });
    10. }
    11. public static void output(Consumer<String> consumer) {
    12. String text = "天将降大任于斯人也,必先苦其心志,劳其筋骨,饿其体肤,空乏其身,行拂乱起所为";
    13. //consumer做什么并不清楚,只有在传入参数时才决定做什么
    14. consumer.accept(text);
    15. }
    16. }
  • Function函数式接口

    1. /**
    2. * 利用Function函数式编程生成定长随机字符串
    3. */
    4. public class FunctionSimple {
    5. public static void main(String[] args) {
    6. Function<Integer, String> randomStringFunction = l -> {
    7. String chars = "abcdefghigklmnopqrstuvwxyz0123456789";
    8. StringBuffer stringBuffer = new StringBuffer();
    9. Random random = new Random();
    10. for (int i = 0; i < l; i++) {
    11. int position = random.nextInt(chars.length());
    12. char c = chars.charAt(position);
    13. stringBuffer.append(c);
    14. }
    15. // return String.valueOf(stringBuffer);
    16. return stringBuffer.toString();
    17. };
    18. String s = randomStringFunction.apply(16);
    19. System.out.println("s = " + s);
    20. }
    21. }
  • 函数式接口特殊检查注解:不满足函数式接口的要求就会报错

    1. @FunctionalInterface //通知编译器这是函数式接口,进行抽象方法检查
    2. public interface MathOperation {
    3. public Float operate(Integer a, Integer b);
    4. }

    Stream流式处理

  • Stream流式处理是建立在Lambda基础上的多数据处理技术

  • Stream对集合数据处理进行高度抽象,极大简化代码量
  • Stream可对集合进行迭代、去重、筛选、排序、聚合等一系列的操作
  • Stream常用方法 | 接口 | 用途 | | —- | —- | | forEach | 循环遍历 | | map | map方法用于映射每个元素到对应的结果 | | filter | filter方法用于通过设置的条件过滤出元素 | | limit | limit方法用于获取指定数量的流 | | sorted | sorted方法用于对流进行排序 | | Collectors | Collectors类实现将流转换成集合和聚合元素 |

  • Stream流的五种创建方式:后三种不常用,了解即可

    1. // 基于数组进行创建
    2. @Test
    3. public void generator1() {
    4. String[] arr = {"Lily", "Andy", "Jackson", "Smith"};
    5. Stream<String> stream = Stream.of(arr);
    6. stream.forEach(s -> System.out.println(s));
    7. }
    8. //基于集合进行创建
    9. @Test
    10. public void generator2() {
    11. List<String> list = new ArrayList<>();
    12. list.add("Lily");
    13. list.add("Andy");
    14. list.add("Jackson");
    15. list.add("Smith");
    16. Stream<String> stream = list.stream();
    17. stream.forEach(s -> System.out.println(s));
    18. }
    19. //利用generator方法创建无限长度流
    20. @Test
    21. public void generator3() {
    22. Stream<Integer> stream = Stream.generate(() -> new Random().nextInt(100000));
    23. // stream.forEach(s -> System.out.println(s));
    24. stream.limit(10).forEach(s -> System.out.println(s));
    25. }
    26. //基于迭代器创建流;使用stream代替创痛的for循环;尽管如此使用较少
    27. @Test
    28. public void generator4() {
    29. Stream<Integer> stream = Stream.iterate(1, n -> n + 1);
    30. stream.limit(10).forEach(s -> System.out.println(s));
    31. }
    32. //基于字符序列创建流
    33. @Test
    34. public void generator5() {
    35. String string = "abcdefg我的";
    36. IntStream stream = string.chars();
    37. stream.forEach(c -> System.out.println((char) c));
    38. }
  • Stream常用方法

    1. //提取集合中所有偶数并对其进行求和操作
    2. @Test
    3. public void case1() {
    4. List<String> list = Arrays.asList("1", "2", "3", "4", "5", "6");
    5. Stream<String> stream = list.stream();//获取stream对象
    6. int sum = stream.mapToInt(s -> Integer.parseInt(s)) //mapToInt将流中每一个数据转换为整数
    7. .filter(n -> n % 2 == 0)// filter对流数据进行过滤
    8. .sum();// 求和
    9. System.out.println("sum = " + sum);
    10. }
    11. //所有名字首字母大写
    12. @Test
    13. public void case2() {
    14. List<String> list = Arrays.asList("lily", "smith", "jackson");
    15. List<String> newList = list.stream()
    16. .map(s -> s.substring(0, 1).toUpperCase() + s.substring(1))//按指定的规则对每一个流数据进行转换,转换的结构仍然保存在当前的流中,无法对外进行输出
    17. // .forEach(s -> System.out.println("s = " + s));
    18. .collect(Collectors.toList());//collect 对流数据进行收集,生成新的List/Set(set会自动取出重复元素)
    19. System.out.println("newList = " + newList);
    20. }
    21. //将所有奇数从大到小进行排序,且不允许出现重复
    22. @Test
    23. public void case3() {
    24. List<Integer> list = Arrays.asList(2,3,2,44,33,67,23);
    25. List<Integer> newList = list.stream()
    26. .distinct() //去除重复的流数据
    27. .filter(n -> n % 2 == 1)
    28. .sorted((a, b) -> b - a) // 需要传入compare方法的实现,前一个参数代表前一个数据数据,
    29. .collect(Collectors.toList());
    30. System.out.println("newList = " + newList);
    31. }