前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >深圳Java培训学习:Java8.0新特性之Lambda表达式

深圳Java培训学习:Java8.0新特性之Lambda表达式

原创
作者头像
深圳java培训技术
修改2019-10-28 18:03:21
4900
修改2019-10-28 18:03:21
举报
文章被收录于专栏:深圳java培训

深圳Java培训学习:Java8.0新特性之Lambda表达式

前言

Java 8 已经发布很久了,很多报道表明Java 8 是一次重大的版本升级。本篇文章,主要给大家介绍的是lambda表达式。

Lambda表达式

Lambda表达式(也称为闭包)是Java 8中最大和最令人期待的语言改变。它允许我们将函数当成参数传递给某个方法,或者把代码本身当作数据处理:函数式开发者非常熟悉这些概念。

很多JVM平台上的语言(Groovy、Scala等)从诞生之日就支持Lambda表达式,但是Java开发者没有选择,只能使用匿名内部类代替Lambda表达式。

Lambda的设计耗费了很多时间和很大的社区力量,最终找到一种折中的实现方案,可以实现简洁而紧凑的语言结构。而lambda表达式的使用需要和函数式接口结合。

1.函数式接口

1.1.概念

函数式接口在Java中是指:有且仅有一个抽象方法的接口。 函数式接口,即适用于函数式编程场景的接口。而Java中的函数式编程体现就是Lambda,所以函数式接口就是可 以适用于Lambda使用的接口。只有确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利地进行推导。 备注:“语法糖”是指使用更加方便,但是原理不变的代码语法。例如在遍历集合时使用的for-each语法,其实 底层的实现原理仍然是迭代器,这便是“语法糖”。从应用层面来讲,Java中的Lambda可以被当做是匿名内部 类的“语法糖”,但是二者在原理上是不同的。

1.2,格式

只要确保接口中有且仅有一个抽象方法即可:

1.修饰符 interface 接口名称 {           

2.    public abstract 返回值类型 方法名称(可选参数信息);  

3.}  

1.3 @FunctionalInterface注解

与 @Override 注解的作用类似,Java 8中专门为函数式接口引入了一个新的注解: @FunctionalInterface 。该注解可用于一个接口的定义上:

1.@FunctionalInterface  

2.public interface MyFunctionalInterface {  

3.    void myMethod();  

4.} 

一旦使用该注解来定义接口,编译器将会强制检查该接口是否确实有且仅有一个抽象方法,否则将会报错。需要注 意的是,即使不使用该注解,只要满足函数式接口的定义,这仍然是一个函数式接口,使用起来都一样.

2.函数式接口的使用

2.1函数式接口作为参数,方法不带参数

1.//定义函数式接口  

2.public interface MyInterface{  

3.      

4.    public abstract void show();  

5.      

6.}  

7.  

8.//使用(匿名内部类对象/函数式)   

9.public class Demo01 {  

10.  

11.    public static void main(String[] args) {  

12.        method01(new MyInterface01() {  

13.  

14.            @Override  

15.            public void show() {  

16.                System.out.println("你好,函数式接口");  

17.            }  

18.        });  

19.        // 函数式  

20.        method01(() -> {  

21.            System.out.println("你好,函数式接口");  

22.        });  

23.        // 函数式简写(如果方法体中只有一句代码)  

24.        method01(() -> System.out.println("你好,函数式接口"));  

25.    }  

26.  

27.    public static void method01(MyInterface01 inter) {  

28.        inter.show();  

29.    }  

30.  

31.} 

函数式接口的优势

函数式接口比匿名内部类对象产生更少的字节码对象,提升java执行效率.

2.2, 函数式接口作为参数,方法带参数

1.//定义函数式接口  

2.    public interface MyInterface02 {  

3.  

4.        public abstract void show(String msg1, String msg2);  

5.  

6.    }  

7.  

8.    //使用函数式接口  

9.    public static void main(String[] args) {  

10.        //匿名内部类对象  

11.        method01(new MyInterface02() {  

12.  

13.            @Override  

14.            public void show(String msg1, String msg2) {  

15.                System.out.println(msg1 + msg2);  

16.            }  

17.        });  

18.        //函数式完整  

19.        method01((String msg1, String msg2) -> {  

20.            System.out.println(msg1 + msg2);  

21.        });  

22.        //函数式简写  

23.        method01((msg1, msg2) -> System.out.println(msg1 + msg2));  

24.  

25.    }  

26.  

27.    public static void method01(MyInterface02 inter) {  

28.        inter.show("hello", "函数式");  

29.    }

2.3, 函数式接口作为返回值,方法不带参数

1.   //定义函数式接口  

2.   public interface MyInterface02 {  

3.  

4.    public abstract void show(String msg1, String msg2);  

5.  

6.   }  

7.public static void main(String[] args) {  

8.  

9.    getInter1().show("你好", "函数式");  

10.    getInter2().show("你好", "函数式");  

11.  

12.}  

13.  

14.// 函数式完整  

15.public static MyInterface02 getInter1() {  

16.  

17.    return (String msg1, String msg2) -> {  

18.        System.out.println(msg1 + msg2);  

19.    };  

20.}  

21.  

22.// 函数式简写  

23.public static MyInterface02 getInter2() {  

24.  

25.    return (msg1, msg2) -> System.out.println(msg1 + msg2);  

26.}  

3.函数式编程应用场景

3.1,概念

在兼顾面向对象特性的基础上,Java语言通过Lambda表达式使用函数式接口,就叫做函数式编程

3.2, 使用lambada作为参数

如果抛开实现原理不说,Java中的Lambda表达式可以被当作是匿名内部类的替代品。如果方法的参数是一个函数 式接口类型,那么就可以使用Lambda表达式进行替代。

1.public class Demo04Runnable{  

2.    private static void startThread(Runnable task){    

3.        new Thread(task).start();   

4.    }        

5.    public static void main(String[] args) {   

6.        startThread(()‐>System.out.println("线程执行"));   

7.    }   

8.}  

3.3, 使用函数式接口作为返回值

如果一个方法的返回值类型是一个函数式接口,那么就可以直接返回一个Lambda表达式。

1.public class Demo06Comparator {  

2.  

3.    private static Comparator<Integer> getComparator(){  

4.        return (num1,num2)‐> num1 - num2;  

5.    }  

6.      

7.    public static void main(String[] args) {  

8.        Integer[] array = {3,2,1};   

9.        Arrays.sort(array, getComparator());   

10.        //遍历数组  

11.    }   

12.} 

3.4, 函数式接口的方法有返回值

1.public static void main(String[] args) {  

2.  

3.        showMsg(new MyInterface03() {  

4.  

5.            @Override  

6.            public String getMsg() {  

7.                return "hello functional interface";  

8.            }  

9.        });  

10.  

11.        // lambada表达式  

12.        showMsg(() -> {  

13.  

14.            return "hello1 functional interface";  

15.        });  

16.  

17.        // lambda表达式简写  

18.        showMsg(() -> "hello1 functional interface");  

19.  

20.    }  

21.  

22.    public static void showMsg(MyInterface03 inter) {  

23.        String msg = inter.getMsg();  

24.        System.out.println(msg);  

25.    } 

4.常用函数式接口(Supplier接口)

JDK提供了大量常用的函数式接口以丰富Lambda的典型使用场景,它们主要在 java.util.function 包中被提供。 下面是简单的几个接口及使用示例。

4.1,Supplier接口

java.util.function.Supplier<T> 接口仅包含一个无参的方法: T get() 。用来获取一个泛型参数指定类型的对象数据。由于这是一个函数式接口,这也就意味着对应的Lambda表达式需要“对外提供”一个符合泛型类型的对象数据

4.2,基本使用

1.private static String getString(Supplier<String> function ){  

2.    return function.get();  

3.}  

4.public static void main(String[] args){  

5.    String msgA="Hello";  

6.    String msgB="World";  

7.    System.out.println(getString(()->msgA+msgB));  

8.}  

4.2,综合案例

需求:使用 Supplier 接口作为方法参数类型,通过Lambda表达式求出int数组中的最大值。提示:接口的泛型请使用 java.lang.Integer 类。

1.public static void main(String[] args) {  

2.    Integer max = getMax(()->{  

3.        Integer[] nums = {1,2,3,4};  

4.        int max2 = nums[0];  

5.        for (Integer num : nums) {  

6.            if(max2 < num){  

7.                max2 = num;  

8.            }  

9.        }  

10.        return max2;  

11.    });  

12.    System.out.println(max);  

13.}  

14.  

15.public static Integer getMax(Supplier<Integer> supplier){  

16.    return supplier.get();  

17.}  

5.常用函数式接口(Consumer接口)

5.1,Consumer接口

java.util.function.Consumer<T> 接口则正好与Supplier接口相反,它不是生产一个数据,而是消费一个数据, 其数据类型由泛型决定

5.2,accept方法

Consumer 接口中包含抽象方法 void accept(T t) ,意为消费一个指定泛型的数据。基本使用如:

1.public static void main(String[] args) {  

2.    consumeString((msg)->System.out.println(msg));  

3.}  

4.  

5.  

6.public static void consumeString(Consumer<String> consumer){  

7.     consumer.accept("hello");  

8.}  

5.3, andThen方法

如果一个方法的参数和返回值全都是 Consumer 类型,那么就可以实现效果:消费数据的时候,首先做一个操作, 然后再做一个操作,实现组合。而这个方法就是 Consumer 接口中的default方法 andThen

1.default Consumer<T> andThen(Consumer<? super T> after) {  

2.    Objects.requireNonNull(after);  

3.    return (T t) -> { accept(t); after.accept(t); };  

4.}  

注: java.util.Objects 的 requireNonNull 静态方法将会在参数为null时主动抛出 NullPointerException 异常。这省去了重复编写if语句和抛出空指针异常的麻烦。

需求:先打印大写HELLO,再打印小写hello

1.public static void main(String[] args) {  

2.    consumeString((msg) -> System.out.println(msg.toUpperCase()),   

3.            (msg) -> System.out.println(msg.toLowerCase()));  

4.}  

5.  

6.public static void consumeString(Consumer<String> consumer1, Consumer<String> consumer2) {  

7.    consumer1.andThen(consumer2).accept("hello");  

8.}  

6.常用函数式接口(Predicate接口)

有时候我们需要对某种类型的数据进行判断,从而得到一个boolean值结果。这时可以使用 java.util.function.Predicate<T> 接口

6.1, test方法

Predicate 接口中包含一个抽象方法: boolean test(T t) 。用于条件判断的场景

1.public enum SingleClass06 {  

2.    INSTANCE;  

3.}

6.2,基本使用

1.public static void main(String[] args) {  

2.    System.out.println(predicateTest((msg) -> msg.length() > 3, "hello"));  

3.}  

4.  

5.  

6.public static boolean predicateTest(Predicate<String> predicate,String msg){  

7.    return predicate.test(msg);  

8.      

9.} 

7.总结

在本文中,我们学会了使用lambda表达式的不同方式,同时也学习了java8.0开始自带的一些常用函数式接口。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档