从零学Java - Lambda表达式

Lambda 表达式

文章目录

  • Lambda 表达式
    • 什么是 Lambda 表达式?
    • 怎么使用?
      • 1 基本语法:
      • 2 箭头符号:
      • 3 代码演示:
      • 4 注意事项
    • 函数式接口
      • 1 什么是函数式接口
      • 2 常见函数式接口
    • 方法引用(了解)
      • 1 什么是方法引用

什么是 Lambda 表达式?

Lambda表达式:特殊的匿名内部类,语法更简洁。

  • 允许把函数作为一个方法的参数(函数作为方法参数传递),将代码像数据一样传递。

怎么使用?

1 基本语法:

<函数式接口>  <变量名> = (参数1,参数2...) -> {
        //方法体
 };

2 箭头符号:

-> (箭头操作符), -> 将表达式分成两部分

  • 左侧:(参数1,参数2…)表示参数列表
  • 右侧:{}内部是方法体

3 代码演示:

public class TestLambda {
    public static void main(String[] args) {
        //Lambda表达式:特殊的匿名内部类,语法更简洁。
        //示例1: Runnable接口
        //匿名内部类:
        Runnable runnable1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("子线程1 开始执行...");
            }
        };
        //简化: Lambda表达式
        Runnable runnable2 = ()->{
            System.out.println("子线程2 开始执行...");
        };
        //使用
        new Thread(runnable1).start();
        new Thread(runnable2).start();

        //简写: 方法体只有一行代码时
        new Thread(()-> System.out.println("子线程3 开始执行..."));

        //示例2: Comparator比较器
        //匿名内部类
        Comparator<Integer> cmp1 = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 - o2;
            }
        };
        //简化: Lambda表达式
        Comparator<Integer> cmp2 = (o1, o2) -> o1 - o2;

        TreeSet<Integer> treeSet1 = new TreeSet<>(cmp1);
        TreeSet<Integer> treeSet2 = new TreeSet<>(cmp2);
    }
}

IDEA 快捷键:

  • 在可以使用 Lambda表达式的位置, 按住 Alt + Enter , 即可将原代码用 Lambda表达式书写

4 注意事项

  • 形参列表的数据类型会自动推断。
  • 如果形参列表为空,只需保留() 。
  • 如果形参只有1个,()可以省略,只需要参数的名称即可。
  • 如果执行语句只有一句,且无返回值,{}可以省略,
    若有返回值,则若想省去{},则必须同时省略return,且执行语句也保证只有一句。
  • Lambda不会生成一个单独的内部类文件。

函数式接口

1 什么是函数式接口

  • 如果一个接口只有一个抽象方法,则该接口称之为函数式接口,函数式接口可以使用Lambda表达式,Lambda表达式会被匹配到这个抽象方法上 。
  • @FunctionalInterface 注解检测接口是否符合函数式接口。

代码示例:

interface:

@FunctionalInterface //函数式接口: 只有一个抽象方法
public interface Usb {
    void service();
}

Test:

public class TestUsb {
    public static void main(String[] args) {
        //匿名内部类
        Usb usb1 = new Usb() {
            @Override
            public void service() {
                System.out.println("连接成功, 开始工作...");
            }
        };

        //Lambda表达式
        Usb usb2 = () -> System.out.println("连接成功, 开始工作...");
    }
}

2 常见函数式接口

函数式接口 参数类型 返回类型 说明
Consumer 消费型接口 T void void accept(T t);对类型为T的对象应用操作
Supplier 供给型接口 T T get(); 返回类型为T的对象
Function 函数型接口 T R R apply(T t);对类型为T的对象应用操作,并返回类型为R类型的对象。
Predicate 断言型接口 T boolean boolean test(T t);确定类型为T的对象是否满足条件,并返回boolean类型。

TestConsumer:

public class TestConsumer {
    public static void main(String[] args) {
        //匿名内部类
        happy(new Consumer<Double>() {
            @Override
            public void accept(Double money) {
                System.out.println(("聚餐吃饭, 花费:"+ money));
            }
        },1000);
        //Lambda表达式
        happy(money-> System.out.println("聚餐吃饭, 花费:"+money),2000);
    }

    public static void happy(Consumer<Double> consumer, double money) {
        consumer.accept(money);
    }
}

TestSupplier:

public class TestSupplier {
    public static void main(String[] args) {
        //匿名内部类
        //获取5个100以内的随机数
        int[] nums1 = getNums(new Supplier<Integer>() {
            @Override
            public Integer get() {
                return new Random().nextInt(100);
            }
        },5);
        System.out.println(Arrays.toString(nums1));
        
        //Lambda表达式
        //获取10个1000以内的随机数
        System.out.println(Arrays.toString(getNums(() -> new Random().nextInt(1000),10)));
    }

    public static int[] getNums(Supplier<Integer> supplier, int length) {
        int[] arr = new int[length];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = supplier.get();
        }
        return arr;
    }
}

TestFunction:

public class TestFunction {
    public static void main(String[] args) {
        //匿名内部类
        String s1 = handleString(new Function<String, String>() {
            @Override
            public String apply(String s) {
                return s.toUpperCase();
            }
        }, "hello");
        System.out.println(s1);
        //Lambda表达式
        System.out.println(handleString(s -> s.toLowerCase(),"HELLO"));
    }

    public static String handleString(Function<String, String> function, String s) {
        return function.apply(s);
    }
}

TestPredicate:

public class TestPredicate {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("张三");
        list.add("张三锋");
        list.add("张耕耘");
        list.add("韩羽");
        list.add("张利");
        list.add("田美丽");
        //匿名内部类
        List<String> list1 = filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.startsWith("张");
            }
        }, list);
        System.out.println(list1);
        //Lambda 表达式
        List<String> list2 = filter(s -> s.startsWith("田"), list);
        System.out.println(list2);
    }

    public static List<String> filter(Predicate<String> p, List<String> src) {
        ArrayList<String> list = new ArrayList<>();
        for (String s : src) {
            if (p.test(s)){
                list.add(s);
            }
        }
        return list;
    }
}

方法引用(了解)

1 什么是方法引用

  • 方法引用是Lambda表达式的一种简写形式。
    • 如果Lambda表达式方法体中只是调用一个特定的已经存在的方法
    • 这个方法的参数和返回值和接口中的方法的参数和返回值保持一致

代码演示:

形式1 : 对象::实例方法

public class TestMethodRef {
    public static void main(String[] args) {
        Consumer<String> consumer1 = s -> System.out.println(s);
        Consumer<String> consumer2 = System.out::println;
        consumer1.accept("xxx");
        consumer2.accept("yyy");
    }
}

res:
xxx
yyy

你可能感兴趣的:(从零学Java,java,开发语言)