全国旗舰校区

不同学习城市 同样授课品质

北京

深圳

上海

广州

郑州

大连

武汉

成都

西安

杭州

青岛

重庆

长沙

哈尔滨

南京

太原

沈阳

合肥

贵阳

济南

下一个校区
就在你家门口
+
当前位置:首页  >  技术问答  > 详情

你所不知道的Lambda表达式和常用的函数式接口

匿名提问者2023-03-27

你所不知道的Lambda表达式和常用的函数式接口

推荐答案

  同学,您好!你所不知道的Lambda表达式和常用的函数式接口

Lambda表达式

  一. 什么是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

  2. 使⽤Lambda必须具有上下⽂推断。 也就是⽅法的参数或局部变量类型必须为Lambda对应的接⼝

  类型,才能使⽤Lambda作为该接⼝的实例。

  5. 常用函数式接口

  JDK提供了⼤量常⽤的函数式接⼝以丰富Lambda的典型使⽤场景,它们主要在 java.util.function

  包中被提供. 常用的函数式接口包括以下四个。

  5.1 Supplier接⼝

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

  5.1.1 基本使用方式如下:

  public class SupplierDemo {

  // 为了获取一个int类型的数据

  private static int getNum(Supplier supplier) {

  // get方法 -- 返回一个指定数据类型 T 的数据

  return supplier.get();

  }

  public static void main(String[] args) {

  // int num = getNum(new Supplier() {

  // @Override

  // public Integer get() {

  // return 50;

  // }

  // });

  System.out.println(getNum(() -> 50));

  // 1. 获取30 60 两个数字中的最大值

  // getNum(new Supplier() {

  // @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() {

  // @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 接⼝则正好与Supplier接⼝相反,它不是⽣产⼀个数据,⽽是消费⼀个数据,其数据类型由泛型决定。

  Consumer 接⼝中包含抽象⽅法 void accept(T t) ,意思是说消费⼀个执⾏泛型的数据

  Consumer 接⼝中包含默认⽅法:andThen

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

  5.2.1 下⾯是JDK的源代码:

  default Consumer andThen(Consumer after) {

  Objects.requireNonNull(after);

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

  }

  基本使用方式如下:

  public class ConsumerDemo {

  // 使用一个指定的String类型的数据

  private static void useString(Consumer consumer, String string){

  consumer.accept(string);

  }

  private static void useString(Consumer consumer, Supplier supplier) {

  consumer.accept(supplier.get());

  }

  // 返回的Consumer对象的目的 -- 使用accept方法接收参数,传递给first和second使用

  private static Consumer andThen(Consumer first, Consumer second){

  return new Consumer() {

  @Override

  public void accept(String s) {

  first.accept(s);

  second.accept(s);

  }

  };

  }

  private static void andThenTest(Consumer first, Consumer second, String string){

  // Consumer then = first.andThen(second);

  // then.accept(string);

  // 前后两个接口对象之间,没有数据上的联系

  // 两个接口 分别处理的都是原本的数据

  first.andThen(second).accept(string);

  System.out.println("---------");

  Consumer consumer = andThen(first, second);

  consumer.accept(string);

  }

  public static void main(String[] args) {

  // useString(new Consumer() {

  // @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 predicate, String s){

  // test方法返回一个boolean类型的数据

  return predicate.test(s);

  }

  private static boolean andMethod(Predicate first, Predicate second, String s){

  return first.and(second).test(s);

  }

  private static boolean orMethod(Predicate first, Predicate second, String s) {

  return first.or(second).test(s);

  }

  private static boolean negateMethod(Predicate predicate, String s) {

  return predicate.negate().test(s);

  }

  public static void main(String[] args) {

  // 1. 判断一个字符串是否是由txt结尾的

  // boolean result = testMethod(new Predicate() {

  // @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 function, String s){

  Integer apply = function.apply(s);

  System.out.println("从字符串" + s + "中获取的integer类型数据是:" + apply);

  }

  private static Function andThen(Function first, Function second){

  // T = String; R = Integer; V=Boolean

  // String --> Boolean

  return new Function() {

  @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 first, Function second, String s){

  Function then = first.andThen(second);

  // 因为andThen方法在实现的时候 前面一个的结果给后面一个处理

  // 前者T R --> 后者 R V ==> T --> V

  Boolean apply = then.apply(s);

  System.out.println(apply);

  System.out.println("------");

  Function function = andThen(first, second);

  Boolean b = function.apply(s);

  System.out.println(b);

  }

  public static void main(String[] args) {

  // applyMethod(new Function() {

  // @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;");

  }

  }

  现在你学会Lambda表达式怎么用了吗?

相关问答

Vue3.0和Vue2.0的区别

Css3有哪些新特性

Vue开发相对于原生的js开发有什么优点

java编程是什么?如何学习java编程?

什么是权限管理?权限管理有哪些分类

开班信息 更多>>

课程名称
全部学科
咨询

HTML5大前端

Java分布式开发

Python数据分析

Linux运维+云计算

全栈软件测试

大数据+数据智能

智能物联网+嵌入式

网络安全

全链路UI/UE设计

Unity游戏开发

新媒体短视频直播电商

影视剪辑包装

游戏原画

    在线咨询 免费试学 教程领取