您的位置:

JDK8 Lambda基础

一、Lambda表达式简介

Lambda表达式是JDK8新加入的一个特性,它是一种新的语言元素,它将匿名函数作为一等公民看待,可以像传递变量一样将它作为参数传递、作为返回值返回、赋值给变量等。Lambda表达式的定义形式为:参数列表 -> 函数体。

例如:

int result = Arrays.asList("apple", "banana", "orange").stream()
            .filter(str -> str.length() > 5)
            .mapToInt(String::length)
            .sum();

上述代码中,Lambda表达式 str -> str.length() > 5 就是过滤条件。

二、Lambda表达式的语法

Lambda表达式的语法包括3个部分:参数列表、箭头符号和函数体,具体详解如下:

  1. 参数列表:表示该Lambda表达式接收哪些参数。可以为空,也可以包含且只包含一个参数、多个参数,参数类型可以明确指定(如:String str)或根据上下文自动推断出来。
  2. 箭头符号:表示下文所要执行的操作。即原来匿名类的方法体,复制左侧参数列表到右侧所要执行的操作,中间使用 -> 符号隔开
  3. 函数体:表示Lambda表达式的执行体,可以是一条语句、一组语句、或者一个表达式。

例如:

// 无参数的Lambda表达式
Runnable r = () -> { System.out.println("Hello Lambda!"); };

// 一个参数的Lambda表达式
Consumer c = (str) -> System.out.println("Hello " + str);

// 多个参数的Lambda表达式
Comparator
    comp = (x, y) -> {
    if (x < y) {
        return -1;
    } else if (x > y) {
        return 1;
    } else {
        return 0;
    }
};

   
  

三、Lambda表达式的应用

1、Lambda表达式与集合

Lambda表达式在集合中的应用十分广泛,可以用来实现各种集合相关的功能,例如过滤、遍历、计算、排序等。以下是一些示例代码:

1.1 过滤
List fruits = Arrays.asList("apple", "banana", "peach", "cherry", "orange");
// 使用Lambda表达式过滤字符串列表中长度大于5的元素
List
    result1 = fruits.stream().filter(str -> str.length() > 5).collect(Collectors.toList());

// 使用Lambda表达式过滤整数列表中大于50的元素
List
     nums = Arrays.asList(10, 20, 30, 40, 50, 60, 70, 80, 90, 100);
List
      result2 = nums.stream().filter(num -> num > 50).collect(Collectors.toList());

     
    
   
  
1.2 遍历
List fruits = Arrays.asList("apple", "banana", "peach", "cherry", "orange");
// 使用Lambda表达式遍历字符串列表
fruits.forEach(str -> System.out.println(str));

// 使用Lambda表达式遍历整数列表
List
    nums = Arrays.asList(10, 20, 30, 40, 50, 60, 70, 80, 90, 100);
nums.forEach(num -> System.out.println(num));

   
  
1.3 计算
// 使用Lambda表达式计算整数列表中元素的和
List nums = Arrays.asList(1, 2, 3, 4, 5);
int sum = nums.stream().mapToInt(num -> num).sum();

// 使用Lambda表达式计算字符串列表中所有元素的长度总和
List
    fruits = Arrays.asList("apple", "banana", "peach", "cherry", "orange");
int lengthSum = fruits.stream().mapToInt(str -> str.length()).sum();

   
  
1.4 排序
List fruits = Arrays.asList("apple", "banana", "peach", "cherry", "orange");
// 使用Lambda表达式对字符串列表进行排序
List
    result1 = fruits.stream().sorted((s1, s2) -> s1.compareTo(s2)).collect(Collectors.toList());

List
     nums = Arrays.asList(10, 5, 20, 30, 15, 25);
// 使用Lambda表达式对整数列表进行排序
List
      result2 = nums.stream().sorted((n1, n2) -> {
    if (n1 < n2) {
        return -1;
    } else if (n1 > n2) {
        return 1;
    } else {
        return 0;
    }
}).collect(Collectors.toList());

     
    
   
  

2、Lambda表达式与函数式接口

函数式接口是一个只包含一个抽象方法的接口,可以通过Lambda表达式实现该接口中的抽象方法,并将Lambda表达式赋值给该接口的实例变量,从而实现函数式编程。

例如java.util.function包中提供了很多常用的函数式接口,例如:Function、Supplier、Consumer、Predicate等。其中Function用于将输入转换为输出,Supplier用于提供输出,Consumer用于处理输入,Predicate用于判断是否符合条件。

以下是一些示例代码:

2.1 Function接口
// 将整数转换成字符串
Function f1 = num -> String.valueOf(num);

// 将字符串转换成整数
Function
    f2 = str -> Integer.parseInt(str);

// 计算字符串长度并返回对应的整数
Function
     f3 = str -> str.length();

    
   
  
2.2 Supplier接口
// 提供当前时间的Supplier接口实现
Supplier s1 = () -> new Date();

// 提供一个随机数的Supplier接口实现
Supplier
    s2 = () -> new Random().nextInt(100);

   
  
2.3 Consumer接口
// 输出整数列表中所有元素
Consumer
   > c1 = list -> {
    for (Integer num : list) {
        System.out.println(num);
    }
};

// 输出字符串列表中所有元素
Consumer
    
     > c2 = list -> {
    for (String str : list) {
        System.out.println(str);
    }
};

     
    
   
  
2.4 Predicate接口
// 判断字符串是否为空
Predicate p1 = str -> str == null || str.isEmpty();

// 判断整数是否是偶数
Predicate
    p2 = num -> num % 2 == 0;

   
  

四、Lambda表达式的优缺点

1、优点

  1. 简化代码:Lambda表达式可以让代码更加简洁、易读,避免了冗长的匿名类形式;
  2. 提高可读性:Lambda表达式的语法更加紧凑、易于理解,可以更好地表达代码的意图;
  3. 提高灵活性:Lambda表达式的功能更加灵活,可以方便地传递方法引用、参数等。

2、缺点

  1. 缺乏可读性:Lambda表达式中的箭头符号和参数列表可能会使代码难以理解;
  2. 不易调试:Lambda表达式中的代码不容易调试,一旦出现错误需要非常小心地排查;
  3. 性能问题:Lambda表达式在执行时可能会带来一些性能问题,但可以通过编写高效的Lambda表达式来避免。

五、总结

Lambda表达式是JDK8中一个很重要的特性,可以用来简化代码、提高可读性、提高灵活性等。需要注意的是,Lambda表达式虽然带来了许多好处,但也存在一些缺点,需要根据实际情况进行选择。