一文搞懂Java8新特性之Lambda表达式

java8新特性之 Lambda表达式

一、适用场合

当使用匿名内部类实现接口,并且接口中有且仅有一个抽象方法时可以使用Lambda表达式。

二、Lambda表达式的写法

Lambda表达式分三部分构成:

() -> {}

中间的 “->” 是Lambda操作符又称箭头操作符;
Lambda操作符左边的“()”中填写Lambda表达式的参数列表;
Lambda操作符左边的“{}”中填写Lambda表达式的方法实现,一般称为Lambda体。

语法规则1:无参数,无返回值

以创建一个新线程为例,使用匿名内部类时的写法:

    @Test
    public void newThread(){
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("创建了一个新线程!!");
            }
        };
        runnable.run();
    }

使用Lambda表达式创建一个新线程:

    @Test
    public void newThreadByLambda(){
        Runnable runnable = () -> {System.out.println("创建了一个新线程!!!");};
        runnable.run();
    }

当Lambda表达式方法体中只有一行代码时,“{}”是可以省略不写的,所以也可这样写:

    @Test
    public void newThreadByLambda(){
        Runnable runnable = () -> System.out.println("创建了一个新线程!!!");
        runnable.run();
    }

语法规则2:一个参数,无返回值

以Java8中自带的函数式接口Consumer为例:
(注:函数式接口的定义下文会提到)

    @Test
    public void lambdaTest1(){
        Consumer<String> consumer = (x) -> System.out.println(x);
        consumer.accept("苏苏可真帅啊!!!");
    }

与Lambda体的“{}”类似,当参数只有一个时,参数的“()” 也可以省略,故以上代码还可以这样写:

    @Test
    public void lambdaTest1(){
        Consumer<String> consumer = x -> System.out.println(x);
        consumer.accept("苏苏可真帅啊!!!");
    }

语法规则3:多个参数,有返回值,并且Lambda体中有多行

以Java8中的函数接口BiPredicate为例:

    @Test
    public void lambdaTest(){
        BiPredicate<String,String> biPredicate = (x, y) ->{
            boolean a = x.equalsIgnoreCase(y);
            return a;
        };
        System.out.println(biPredicate.test("hello","Hello"));
        System.out.println(biPredicate.test("hello","world"));
    }

Lambda表达式中参数的数据类型可以不写,比如上面的例子中x和y的数据类型String就省略了

三、函数式接口

Lambda表达式的函数式编程需要函数式接口的支持。

函数式接口的定义:接口中只有一个抽象方法的接口叫函数式接口

函数式接口可以使用@FunctionalIterface注解标识。

定义一个函数式接口:

@FunctionalInterface
public interface myService<T> {
    Object getValue(T t);
}

调用自定义的函数式接口:

    public String stringHandler(String s,MyService<String> myService){
        return (String) myService.getValue(s);
    }
    @Test
    public void test6(){
        MyService<String> myService = x -> x.toUpperCase();
        System.out.println(myService.getValue("oh no!"));
        String result = stringHandler("a ha!",x -> x.toUpperCase());
        System.out.println(result);
    }

四、Java8中内置的函数式接口

为了防止使用Lambda表达式时都必须手动添加接口,Java8内置了四大核心函数式接口:

/*
 * Consumer<T> :消费型接口
 * 参数类型:T 
 * 返回类型:void 
 * void acept(T t);
   
 *
 * Supplier<T> :供给型接口
 * 参数类型:无 
 * 返回类型:T
 * T get();
 *
 * Function<T,R> :函数型接口
 * 参数类型:T
 * 返回类型:R
 * R apply(T t);
 *
 * Predicate<T> :断言型接口
 * 参数类型:T
 * 返回类型:boolean
 * boolean test(T t);
 

消费型接口

    //打印出消费了多少钱
    public void cost(Double d, Consumer<Double> consumer){
        consumer.accept(d);
    }
    
    @Test
    public void test1(){
        cost(998.00,x -> System.out.println("苏苏去超市购物消费" + x + "元!!!!"));
    }

供给型接口

    //产生指定个数的整数,并放入List中
    public List<Integer> getNumList(int num, Supplier<Integer> supplier){
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            Integer n = supplier.get();
            list.add(n);
        }
        return list;
    }
    @Test
    public void test2(){
        List<Integer> list = getNumList(10,() -> (int)Math.random());
        System.out.println(list);
    }

函数型接口

    //处理字符串
    public String strHandler(String s, Function<String,String> function){
        return function.apply(s);
    }
    @Test
    public void test3(){
        //将字符串转换成大写
        String strUpper = strHandler("insuonante",x -> x.toUpperCase());
        System.out.println(strUpper);
    }

断言型接口

    //输入数字,判断是否大于0
    @Test
    public void test4(){
        Predicate<Integer> predicate = (x) -> x > 0;
        System.out.println(predicate.test(10));
    }

其他内置接口

BiFunction< T, U, R >

BiConsumer< T, U >

BinaryOperator< T >

...

五、引用

三种方法引用写法:

对象::实例方法

    @Test
    public void test(){
        Consumer<String> consumer = System.out::println;
        consumer.accept("到饭点了,我真的好饿啊!");
    }

类::静态方法

    @Test
    public void test(){
        Consumer<Integer> consumer = String::valueOf;
        consumer.accept(1);
    }

类::实例方法

    @Test
    public void test(){
        Consumer<String> consumer = String::trim;
        consumer.accept(" 到饭点了,我真的好饿啊!   ");
    }

构造器引用: ClassName::new

    @Test
    public void test(){
        Supplier<String> supplier = String::new;
        System.out.println(supplier.equals("到饭点了,我真的好饿啊!"));
    }

数组引用:Type::new

    @Test
    public void test(){
        Function<Integer,String[]> function = String[]::new;
        String[] strings = function.apply(20);
        System.out.println(strings.length);
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容