一. 什么是Lambda表达式
Lambda表达式是JDK1.8中新增的一种方式,用于替代匿名内部类,该表达式可以让开发人员更加关注于具体需要传递的方法,而不是因为需要传递一个方法而创建一个对象。
二. Lambda表达式
1.基本语法
Lambda省去⾯向对象的条条框框,格式由3个部分组成:
参数部分
箭头
代码块
比如:(参数类型 参数名称) -> { 代码语句 }
2.格式说明
⼩括号内的语法与传统⽅法参数列表⼀致:⽆参数则留空;多个参数则⽤逗号分隔;
-> 是新引⼊的语法格式,代表指向动作;
⼤括号内的语法与传统⽅法体要求基本⼀致。
3.Lambda的省略格式
所谓的Lambda表达式的省略原则是:可推导即可省略。
Lambda强调的是“做什么”⽽不是“怎么做”,所以凡是可以根据上下⽂推导得知的信息,都可以省略。
3.1 省略规则
在Lambda标准格式的基础上,使⽤省略写法的规则为:
⼩括号内参数的类型可以省略;
如果⼩括号内有且仅有⼀个参,则⼩括号可以省略;
如果⼤括号内有且仅有⼀个语句,则⽆论是否有返回值,都可以省略⼤括号、return关键字及语句、分号。
4.Lambda的使用前提
Lambda的语法⾮常简洁,完全没有⾯向对象复杂的束缚,但是使⽤时有⼏个问题需要特别注意:
使⽤Lambda必须具有接⼝,且要求接口中有且仅有⼀个抽象方法。⽆论是JDK内置的Runnable 、 Comparator 接⼝还是⾃定义的接⼝,只有当接⼝中的抽象⽅法存在且唯⼀时,才可以使⽤Lambda。
使⽤Lambda必须具有上下文推断。也就是⽅法的参数或局部变量类型必须为Lambda对应的接⼝类型,才能使⽤Lambda作为该接⼝的实例。
5.常用函数式接口
JDK提供了⼤量常⽤的函数式接⼝以丰富Lambda的典型使⽤场景,它们主要在 java.util.function
包中被提供. 常用的函数式接口包括以下四个。
5.1 Supplier接口
java.util.function.Supplier
5.1.1 基本使用方式如下:
- public class SupplierDemo {
-
- // 为了获取一个int类型的数据
- private static int getNum(Supplier<Integer> supplier) {
- // get方法 -- 返回一个指定数据类型 T 的数据
- return supplier.get();
- }
-
- public static void main(String[] args) {
- // int num = getNum(new Supplier<Integer>() {
- // @Override
- // public Integer get() {
- // return 50;
- // }
- // });
-
- System.out.println(getNum(() -> 50));
-
- // 1. 获取30 60 两个数字中的最大值
- // getNum(new Supplier<Integer>() {
- // @Override
- // public Integer get() {
- // return Math.max(30, 60);
- // }
- // });
- getNum(()->Math.max(30, 60));
-
- // 有一个数组
- int[] nums = {1,5,4,8,4,51,2,1,6,8};
- // 通过getNum方法获取数组的最大值
- // getNum(new Supplier<Integer>() {
- // @Override
- // public Integer get() {
- // Arrays.sort(nums);
- // return nums[nums.length - 1];
- // }
- // });
-
- int num = getNum(() -> {
- Arrays.sort(nums);
- return nums[nums.length - 1];
- });
- System.out.println(num);
- }
- }
5.2 Consumer接口
java.util.function.Consumer
Consumer接口中包含抽象⽅法 void accept(T t) ,意思是说消费⼀个执⾏泛型的数据
Consumer 接⼝中包含默认⽅法:andThen
如果⼀个⽅法的参数和返回值全都是 Consumer 类型,那么就可以实现效果:消费数据的时候,⾸先做⼀个操作, 然后再做另⼀个操作,实现组合。⽽这个⽅法就是 Consumer 接⼝中的default⽅法 andThen。
5.2.1 下⾯是JDK的源代码:
- default Consumer<T> andThen(Consumer<? super T> after) {
- Objects.requireNonNull(after);
- return (T t) -> { accept(t); after.accept(t); };
- }
- 基本使用方式如下:
- public class ConsumerDemo {
-
- // 使用一个指定的String类型的数据
- private static void useString(Consumer<String> consumer, String string){
- consumer.accept(string);
- }
-
- private static void useString(Consumer<String> consumer, Supplier<String> supplier) {
- consumer.accept(supplier.get());
- }
-
-
- // 返回的Consumer对象的目的 -- 使用accept方法接收参数,传递给first和second使用
- private static Consumer<String> andThen(Consumer<String> first, Consumer<String> second){
- return new Consumer<String>() {
- @Override
- public void accept(String s) {
- first.accept(s);
- second.accept(s);
- }
- };
- }
- private static void andThenTest(Consumer<String> first, Consumer<String> second, String string){
- // Consumer<String> then = first.andThen(second);
- // then.accept(string);
- // 前后两个接口对象之间,没有数据上的联系
- // 两个接口 分别处理的都是原本的数据
- first.andThen(second).accept(string);
- System.out.println("---------");
- Consumer<String> consumer = andThen(first, second);
- consumer.accept(string);
- }
-
- public static void main(String[] args) {
- // useString(new Consumer<String>() {
- // @Override
- // public void accept(String s) {
- // System.out.println(s.length());
- // }
- // }, "lambda");
-
- // useString((String s)->{
- // System.out.println(s.length());
- // }, "lambda");
- useString(s->System.out.println(s.length()), "lambda");
- // useString(s-> System.out.println(s), "lambda");
- // useString(System.out::println, "lambda");
-
- useString(s-> {
- System.out.println(s.concat(Integer.valueOf(s.length()).toString()));
- System.out.println(s + s.length());
- }, "lambda");
-
- useString(s->{
- System.out.println(s.length());
- },()->{
- return "123456oiuytr";
- });
-
- andThenTest(s -> System.out.println(s.toUpperCase()),
- s->System.out.println(s.substring(0, 3)), "lambda Exp");
- }
- }
5.3 Predicate接口
有时候我们需要对某种类型的数据进⾏判断,从⽽得到⼀个boolean值结果。这时可以使
⽤java.util.function.Predicate
Predicate 接⼝中包含⼀个抽象⽅法:boolean test(T t)
该接口也存在三个默认的方法,分别是and 、 or 和negate, 分别表示与 、或 、非三种逻辑处理。
5.3.1 接口代码示例
- public class PredicateDemo {
-
- private static boolean testMethod(Predicate<String> predicate, String s){
- // test方法返回一个boolean类型的数据
- return predicate.test(s);
- }
-
- private static boolean andMethod(Predicate<String> first, Predicate<String> second, String s){
- return first.and(second).test(s);
- }
-
- private static boolean orMethod(Predicate<String> first, Predicate<String> second, String s) {
- return first.or(second).test(s);
- }
-
- private static boolean negateMethod(Predicate<String> predicate, String s) {
- return predicate.negate().test(s);
- }
-
- public static void main(String[] args) {
- // 1. 判断一个字符串是否是由txt结尾的
- // boolean result = testMethod(new Predicate<String>() {
- // @Override
- // public boolean test(String s) {
- // return s.endsWith("txt");
- // }
- // }, "newFile");
- // boolean result = testMethod((String s)->{
- // return s.endsWith("txt");
- // }, "newFile");
- boolean result = testMethod(s->s.endsWith("txt"), "newFile");
- System.out.println(result);
-
- boolean r1 = andMethod(s -> s.length() > 6,
- s -> s.startsWith("a"), "asijhgvbnm");
-
- boolean r2 = orMethod(s -> s.length() > 6,
- s -> s.equals("abcd"), "asdfghjkl");
-
- boolean r3 = negateMethod(s -> s.endsWith("a"), "asdfghjkl");
-
- System.out.println(r1 + " - " + r2 + " - " + r3);
- }
- }
5.4 Function接口
java.util.function.Function
Function 接⼝中最主要的抽象⽅法是:R apply(T t) ,根据类型T的参数获取类型R的结果。
Function接⼝中有⼀个默认的andThen⽅法,⽤来进⾏组合操作。
5.4.1 基本使用方式如下
- public class FunctionDemo {
-
- private static void applyMethod(Function<String, Integer> function, String s){
- Integer apply = function.apply(s);
- System.out.println("从字符串" + s + "中获取的integer类型数据是:" + apply);
- }
-
- private static Function<String, Boolean> andThen(Function<String, Integer> first, Function<Integer, Boolean> second){
- // T = String; R = Integer; V=Boolean
- // String --> Boolean
- return new Function<String, Boolean>() {
- @Override
- public Boolean apply(String s) {
- // String --> Integer
- Integer apply = first.apply(s);
- // Integer --> Boolean
- Boolean apply1 = second.apply(apply);
- return apply1;
- }
- };
- }
- private static void andThenMethod(Function<String, Integer> first, Function<Integer, Boolean> second, String s){
- Function<String, Boolean> then = first.andThen(second);
- // 因为andThen方法在实现的时候 前面一个的结果给后面一个处理
- // 前者T R --> 后者 R V ==> T --> V
- Boolean apply = then.apply(s);
- System.out.println(apply);
-
- System.out.println("------");
-
- Function<String, Boolean> function = andThen(first, second);
- Boolean b = function.apply(s);
- System.out.println(b);
- }
-
- public static void main(String[] args) {
- // applyMethod(new Function<String, Integer>() {
- // @Override
- // public Integer apply(String s) {
- // return s.indexOf("a");
- // }
- // }, "fashjkl");
-
- // applyMethod((String s)->{
- // return s.indexOf("a");
- // }, "fashjkl");
-
- applyMethod(s->s.indexOf("a"), "fashjkl");
-
- andThenMethod(s-> s.length(),
- i -> i > 20, "sadfghjkl;");
-
- // andThenMethod(String::length,
- // i -> i > 20, "sadfghjkl;");
- }
- }