一、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个部分:参数列表、箭头符号和函数体,具体详解如下:
- 参数列表:表示该Lambda表达式接收哪些参数。可以为空,也可以包含且只包含一个参数、多个参数,参数类型可以明确指定(如:String str)或根据上下文自动推断出来。
- 箭头符号:表示下文所要执行的操作。即原来匿名类的方法体,复制左侧参数列表到右侧所要执行的操作,中间使用 -> 符号隔开
- 函数体:表示Lambda表达式的执行体,可以是一条语句、一组语句、或者一个表达式。
例如:
// 无参数的Lambda表达式 Runnable r = () -> { System.out.println("Hello Lambda!"); }; // 一个参数的Lambda表达式 Consumerc = (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 过滤
Listfruits = 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 遍历
Listfruits = 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表达式计算整数列表中元素的和 Listnums = 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 排序
Listfruits = 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接口
// 将整数转换成字符串 Functionf1 = num -> String.valueOf(num); // 将字符串转换成整数 Function f2 = str -> Integer.parseInt(str); // 计算字符串长度并返回对应的整数 Function f3 = str -> str.length();
2.2 Supplier接口
// 提供当前时间的Supplier接口实现 Suppliers1 = () -> 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接口
// 判断字符串是否为空 Predicatep1 = str -> str == null || str.isEmpty(); // 判断整数是否是偶数 Predicate p2 = num -> num % 2 == 0;
四、Lambda表达式的优缺点
1、优点
- 简化代码:Lambda表达式可以让代码更加简洁、易读,避免了冗长的匿名类形式;
- 提高可读性:Lambda表达式的语法更加紧凑、易于理解,可以更好地表达代码的意图;
- 提高灵活性:Lambda表达式的功能更加灵活,可以方便地传递方法引用、参数等。
2、缺点
- 缺乏可读性:Lambda表达式中的箭头符号和参数列表可能会使代码难以理解;
- 不易调试:Lambda表达式中的代码不容易调试,一旦出现错误需要非常小心地排查;
- 性能问题:Lambda表达式在执行时可能会带来一些性能问题,但可以通过编写高效的Lambda表达式来避免。
五、总结
Lambda表达式是JDK8中一个很重要的特性,可以用来简化代码、提高可读性、提高灵活性等。需要注意的是,Lambda表达式虽然带来了许多好处,但也存在一些缺点,需要根据实际情况进行选择。