当前位置:   article > 正文

JDK8新特性之Lambda表达式_jdk8 lamda

jdk8 lamda

目录

一、JDK8的特性

二、Lambda表达式

2.1 lambda的由来

2.2 lambda表达式初体验

2.3 lambda表达式的语法

2.4 无参无返回值的Lambda表达式

2.5 有参有返回值的Lambda表达式

2.6 Lambda表达式的省略写法

2.7 Lambda表达式使用的前提

三、内置函数式接口

3.1 内置函数式接口的由来

3.2 消费性函数式接口Consumer

3.3 供给型函数式接口Supplier

3.4 函数型函数式接口Function,r>

3.5 断言型函数式接口Predicate

四、方法引用

4.1 方法引用的由来

4.2 方法引用的类型


一、JDK8的特性

1. Lambda表达式
2. 函数式接口
3. 方法引用。
4. Stream流
5. 日期时间类

二、Lambda表达式

2.1 lambda的由来

  1. package demo02;
  2. /**
  3. * @author huihui
  4. * @Project jdk8
  5. * @date 2023/6/13 14:52
  6. */
  7. public class Test02 {
  8. public static void main(String[] args) {
  9. //开启线程 该构造函数需要传递一个Runnable类型的接口参数
  10. Thread thread = new Thread(new my());
  11. thread.start();//开启线程
  12. //匿名内部类
  13. Thread thread1=new Thread(new Runnable() {
  14. @Override
  15. public void run() {
  16. System.out.println("通过匿名内部类实现线程任务");
  17. }
  18. });
  19. }
  20. }
  21. class my implements Runnable{
  22. @Override
  23. public void run() {
  24. System.out.println("使用实现类来完成---->线程任务");
  25. }
  26. }

分析:

  1. Thread类需要一个Runnable接口作为参数,其中的抽象方法run方法是用来指定线程任务内容的核心

  2. 为了指定run方法体,不得不需要Runnable的实现类

  3. 为了省去定义一个Runnable 的实现类,不得不使用匿名内部类

  4. 必须覆盖重写抽象的run方法,所有的方法名称,方法参数,方法返回值不得不都重写一遍,而且不能出错,

  5. 而实际上,我们只在乎方法体中的代码.

我们可以使用lambda表达式来完成上面的功能

2.2 lambda表达式初体验

  1. //lambda表达式.
  2. Runnable runnable1=()->{
  3. System.out.println("这是lambda表达式完成线程任务");
  4. };
  5. Thread thread2=new Thread(runnable1);
  6. thread2.start();

2.3 lambda表达式的语法

(参数列表)-->{}

():参数列表

->:连接符 连接的是参数以及方法体。

{}:方法体

2.4 无参无返回值的Lambda表达式

  1. package demo03;
  2. /**
  3. * @author huihui
  4. * @Project jdk8
  5. * @date 2023/6/13 15:17
  6. */
  7. public class Test03 {
  8. public static void main(String[] args) {
  9. //主函数调用fun方法。
  10. //第一种:创建UserService接口的实现类,并创建该实现类对象
  11. //第二种:匿名内部类的方式
  12. // UserService userService = new UserService() {
  13. // @Override
  14. // public void show() {
  15. // System.out.println("这是匿名内部类的show方法的实现");
  16. // }
  17. // };
  18. // fun(userService);
  19. //第三种lambda表达式:--该接口必须为函数式接口
  20. UserService userService = ()->{
  21. System.out.println("lambda表示的show方法");
  22. };
  23. fun(userService);
  24. }
  25. public static void fun(UserService userService){
  26. userService.show();
  27. }
  28. }
  29. //函数式接口-->里面有且仅有一个抽象方法。--只有这种接口才能使用lambda表达式
  30. interface UserService{
  31. public void show();
  32. }

2.5 有参有返回值的Lambda表达式

  1. package demo04;
  2. import com.sun.org.apache.bcel.internal.generic.NEW;
  3. import java.util.ArrayList;
  4. import java.util.Collections;
  5. import java.util.Comparator;
  6. import java.util.List;
  7. /**
  8. * @author huihui
  9. * @Project jdk8
  10. * @date 2023/6/13 16:14
  11. */
  12. public class Test04 {
  13. public static void main(String[] args) {
  14. List<Person> personList = new ArrayList<>();
  15. personList.add(new Person("张三",65));
  16. personList.add(new Person("李四",55));
  17. personList.add(new Person("王五",30));
  18. personList.add(new Person("赵六",47));
  19. personList.add(new Person("田七",31));
  20. System.out.println(personList);
  21. //对集合中的元素按照年龄排序,从小到大
  22. //Collections:集合工具类。--匿名内部类
  23. // Comparator<Person> comparator = new Comparator<Person>(){
  24. // @Override //如果是0表示相同 大于0表示o1大于02
  25. // public int compare(Person o1, Person o2) {
  26. // return o1.getAge()-o2.getAge();
  27. // }
  28. // };
  29. // Collections.sort(personList,comparator);
  30. // System.out.println(personList);
  31. Comparator<Person> comparator=(o1, o2) -> {
  32. //就是对函数式接口中抽象方法的简写
  33. return o1.getAge()-o2.getAge();
  34. };
  35. Collections.sort(personList,comparator);
  36. System.out.println(personList);
  37. }
  38. }
  39. class Person {
  40. private String name;
  41. private Integer age;
  42. public Person() {
  43. }
  44. public Person(String name, Integer age) {
  45. this.name = name;
  46. this.age = age;
  47. }
  48. /**
  49. * 获取
  50. * @return name
  51. */
  52. public String getName() {
  53. return name;
  54. }
  55. /**
  56. * 设置
  57. * @param name
  58. */
  59. public void setName(String name) {
  60. this.name = name;
  61. }
  62. /**
  63. * 获取
  64. * @return age
  65. */
  66. public Integer getAge() {
  67. return age;
  68. }
  69. /**
  70. * 设置
  71. * @param age
  72. */
  73. public void setAge(Integer age) {
  74. this.age = age;
  75. }
  76. public String toString() {
  77. return "Person{name = " + name + ", age = " + age + "}";
  78. }
  79. }

2.6 Lambda表达式的省略写法

 在lambda表达式的标准写法基础上,可以使用省略写法的规则为:

  1. 小括号内的参数类型可以省略[]

  2. 如果小括号内有且仅有一个参数,则小括号可以省略

  3. 如果大括号内有且仅有一个语句,可以同时省略大括号,return 关键字及语句分号。

  1. package demo05;
  2. /**
  3. * @author huihui
  4. * @Project jdk8
  5. * @date 2023/6/13 16:30
  6. */
  7. public class Test05 {
  8. public static void main(String[] args) {
  9. USB u=str -> str.toUpperCase();//Lambda表达式;
  10. // USB u = new USB() { //匿名内部类对接口中抽象方法的个数没有任何要求
  11. // @Override
  12. // public String toUpper(String str) {
  13. // return null;
  14. // }
  15. //
  16. // @Override
  17. // public String toLower(String str) {
  18. // return null;
  19. // }
  20. // };
  21. fun(u);
  22. }
  23. public static void fun(USB usb){
  24. String s = usb.toUpper("hello");
  25. System.out.println(s);
  26. }
  27. }
  28. interface USB {
  29. public String toUpper(String str);
  30. // public String toLower(String str);
  31. }

2.7 Lambda表达式使用的前提

Lambda表达式的语法是非常简洁的,但是Lambda表达式不是随便使用的,使用时有几个条件要特别注意

  1. 方法的参数或局部变量类型必须为接口才能使用Lambda

  2. 接口中有且仅有一个抽象方法(@FunctionalInterface)

后面我们使用lambda表达式主要核心使用再Stream流中。

三、内置函数式接口

要想使用lambda表达式它的前提就是必须是函数式接口。

3.1 内置函数式接口的由来

  1. package demo06;
  2. /**
  3. * @author huihui
  4. * @Project jdk8
  5. * @date 2023/6/13 17:07
  6. */
  7. public class Test06 {
  8. public static void main(String[] args) {
  9. Operation o=arr -> {
  10. int sum = 0;
  11. for(int s :arr){
  12. sum+=s;
  13. }
  14. return sum;
  15. };
  16. fun(o);
  17. }
  18. public static void fun(Operation operation){
  19. int[] arr = {1,2,3,4};
  20. int s = operation.getSum(arr);
  21. System.out.println("数组的和为:"+s);
  22. }
  23. }
  24. @FunctionalInterface
  25. interface Operation {
  26. public int getSum(int[] arr);
  27. }

分析:

我们知道使用Lambda表达式的前提是需要有函数式接口,而Lambda表达式使用时不关心接口名,抽象方法名。只关心抽象方法的参数列表和返回值类型。因此为了让我们使用Lambda表达式更加的方便,在JDK中提供了大量常用的函数式接口. 大多数无需自己再定义函数式接口,而可以直接使用jdk内置的函数式接口。分成四类。

  • 函数式接口的分类

函数式接口

参数类型

返回类型

说明

Consumer<T>

消费型接口

T

void

void accept(T t);对类型为T的对象应用操作

Supplier<T>

供给型接口

T

T get(); 返回类型为T的对象

Function<T,R>

函数型接口

T

R

R apply(T t);对类型为T的对象应用操作,并返回类型为R类型的对象。

Predicate<T>

断言型接口

T

boolean

boolean test(T t);确定类型为T的对象是否满足条件并返回boolean类型。

3.2 消费性函数式接口Consumer

适合有参数,但是没有返回值的

  1. package demo07;
  2. import java.util.function.Consumer;
  3. /**
  4. * @author huihui
  5. * @Project jdk8
  6. * @date 2023/6/13 17:23
  7. */
  8. public class Test07 {
  9. public static void main(String[] args) {
  10. Consumer<Double> c=t->{
  11. System.out.println("今天吃饭花费:"+t+"元");
  12. };
  13. fun(c,20.5);
  14. }
  15. public static void fun(Consumer<Double> consumer,Double money){
  16. consumer.accept(money);
  17. }
  18. }

3.3 供给型函数式接口Supplier

无参,需要返回值的接口类

  1. package demo08;
  2. import java.util.Random;
  3. import java.util.function.Consumer;
  4. import java.util.function.Supplier;
  5. /**
  6. * @author huihui
  7. * @Project jdk8
  8. * @date 2023/6/13 17:23
  9. */
  10. public class Test08 {
  11. public static void main(String[] args) {
  12. // Supplier<Integer> s = ()->new Random().nextInt(10);//十以内的随机数
  13. // fun(s);
  14. fun(()->new Random().nextInt(10));
  15. }
  16. public static void fun(Supplier<Integer> supplier){
  17. Integer a = supplier.get();
  18. System.out.println("结果:"+a);
  19. }
  20. }

3.4 函数型函数式接口Function<T,R>

T: 参数的泛型

R:返回值的泛型

  1. package demo09;
  2. import java.util.function.Function;
  3. /**
  4. * @author huihui
  5. * @Project jdk8
  6. * @date 2023/6/13 17:35
  7. */
  8. public class Test09 {
  9. public static void main(String[] args) {
  10. Function<int[],Integer> o=arr->{
  11. int sum = 0;
  12. for(int s:arr){
  13. sum+=s;
  14. }
  15. return sum;
  16. };
  17. fun(o);
  18. }
  19. public static void fun(Function<int[],Integer> fun){
  20. int[] arr={1,2,3,4};
  21. int s = fun.apply(arr);
  22. System.out.println("数组的和:"+s);
  23. }
  24. }

3.5 断言型函数式接口Predicate

T: 参数

boolean:返回值类型

  1. package demo10;
  2. import java.util.function.Predicate;
  3. /**
  4. * @author huihui
  5. * @Project jdk8
  6. * @date 2023/6/13 19:15
  7. */
  8. public class Test10 {
  9. public static void main(String[] args) {
  10. Predicate<String> p = t->t.length()>3;
  11. fun(p,"迪丽热巴");
  12. }
  13. public static void fun(Predicate<String> predicate,String name){
  14. boolean test = predicate.test(name);
  15. System.out.println("名字是否够长:"+test);
  16. }
  17. }

四、方法引用

特殊的lambda表达式,它是对lambda表达式的一种简写方式。

4.1 方法引用的由来

  1. package demo11;
  2. import java.util.function.Consumer;
  3. /**
  4. * @author huihui
  5. * @Project jdk8
  6. * @date 2023/6/13 19:38
  7. */
  8. public class Test11 {
  9. public static void main(String[] args) {
  10. Consumer<int[]> c= t->{
  11. int sum=0;
  12. for(int a:t){
  13. sum+=a;
  14. }
  15. System.out.println("数组的和:"+sum);
  16. };
  17. fun(c);
  18. }
  19. public static void fun(Consumer<int[]> consumer){
  20. int[] arr={1,2,3,4,5};
  21. consumer.accept(arr);
  22. }
  23. //求和方法
  24. public static void sum(int[] arr){
  25. int sum=0;
  26. for(int a:arr){
  27. sum+=a;
  28. }
  29. System.out.println("数组的和:"+sum);
  30. }
  31. }

如果我们在Lambda中所指定的功能,已经有其他方法存在相同方案,那是否还有必要再写重复逻辑?可以直接“引 用”过去就好了:---方法引用   ::

  1. package demo11.demo12;
  2. import demo11.Test11;
  3. import java.util.function.Consumer;
  4. /**
  5. * @author huihui
  6. * @Project jdk8
  7. * @date 2023/6/13 19:40
  8. */
  9. public class Test12 {
  10. public static void main(String[] args) {
  11. // Consumer<int[]> c=t->{
  12. // int sum=0;
  13. // for(int a:t){
  14. // sum+=a;
  15. // }
  16. // System.out.println("数组的和:"+sum);
  17. // };
  18. // Consumer<int[]> c=(t)->Test07.sum(t); //
  19. Consumer<int[]> c = Test11::sum;
  20. fun(c);
  21. }
  22. public static void fun(Consumer<int[]> consumer) {
  23. int[] arr = {1, 2, 3, 4, 5};
  24. consumer.accept(arr);
  25. }
  26. //求和方法
  27. public static void sum(int[] arr) {
  28. int sum = 0;
  29. for (int a : arr) {
  30. sum += a;
  31. }
  32. System.out.println("数组的和:" + sum);
  33. }
  34. }

4.2 方法引用的类型

类型

语法

对应的Lambda表达式

静态方法引用

类名::staticMethodd

(args) -> 类名.staticMethod(args)

实例方法引用

inst::instMethod

(args) -> inst.instMethod(args)

对象方法引用

类名::instMethod

(inst,args) -> inst.instMethod(args)

构建方法引用

类名::new

(args) -> new 类名(args)

方法引用是Lambda表达式的一种简写形式。如果Lambda表达式方法中只是调用一个特定已经存在的方法,则可以使用方法引用。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/726786
推荐阅读
相关标签
  

闽ICP备14008679号