lamda表达式(史上最全)

一、函数式接口

在jdk8中什么是函数式接口:

  1. 被@FunctionalInterface注解修饰的。
  2. 接口里边只有一个非default的方法。

满足以上2个条件的即为函数式接口,ps:即使一个接口没有@FunctionalInterface修饰,但是满足2,那么这样的接口也会是函数式接口。

二、函数式接口的特点

  • 接口有且仅有一个抽象方法,如上图的抽象方法compare
  • 允许定义静态非抽象方法
  • 允许定义默认defalut非抽象方法(default方法也是java8才有的,见下文)
  • 允许java.lang.Object中的public方法,如上图的方法equals。
  • FunctionInterface注解不是必须的,如果一个接口符合"函数式接口"定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错

情况一

  • 接口有且仅有一个抽象方法,且加上了@FunctionInterface注解
@FunctionalInterface
public interface test_lamda {void show();
}public class test {public static void main(String[] args) {test_lamda test_lamda=()->{System.out.println("test");};test_lamda.show();}
}

情况二

  • 接口有且仅有一个抽象方法,且没有加上了@FunctionInterface注解
public interface test_lamda {void show();
}public class test {public static void main(String[] args) {test_lamda test_lamda=()->{System.out.println("test");};test_lamda.show();}
}

情况三

  • 使用java.lang.Object中的public方法
public interface test_lamda {void show();boolean equals(Object obj);
}public class test {public static void main(String[] args) {test_lamda test_lamda=()->{System.out.println("test");};test_lamda.show();}
}

情况四

定义静态抽象方法,定义default

public interface test_lamda {void show();static void test1() {System.out.println("test");}default void test2() {System.out.println("test");}
}public class test {public static void main(String[] args) {test_lamda test_lamda=()->{System.out.println("test");};test_lamda.show();}
}

情况五

定义两个抽象方法

public interface test_lamda {void show();void test();
}

三、Lamda表达式

1.背景

Java8的最大变化是引入了Lambda表达式,它是所有Java8特性内容的基础——一种紧凑的,传递行为的方式。lambda表达式允许你通过表达式来代替功能接口,lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体, Lambda 表达式(Lambda expression)可以看作是一个匿名函数,也称为闭包

2.Lambda表达式语法

基本语法: (parameters) -> expression 或 (parameters) ->{ statements; }

Lambda表达式由三部分组成:

  1. parameters:参数,类似方法中的形参列表,这里的参数是函数式接口里的参数
  2. ->:可理解为“被用于”的意思
  3. 方法体:可以是表达式也可以代码块,是函数式接口里方法的实现。代码块可返回一个值或者什么都不反回,这里的代码块等同于方法的方法体。如果是表达式,也可以返回一个值或者什么都不返回

3.Lambda表达式五种不同的形式

//1、无需要参数,使用空括号()表示没有参数。
//该Lambda表达式实现了Runnable接口,该接口也只有一个run方法,没有参数,返回值类型为void
Runnable noArguments = () -> System.out.println("Hello World")
// 2. 接收一个参数,可以省略括号,返回其2倍的值
x -> 2 * x
//3. Lambda表达式主体不仅可以是表达式,也可以是一段代码块,使用大括号{}将代码括起来。
() ->{System.out.println("Hello");System.out.println("World")
}
//4.Lambda表达式可以包含多个参数的方法。接受2个参数(数字),并返回他们的和
(x,y)->x+y;
//5.声明是参数类型,也可以是多个参数。接收2个int型整数,返回他们的和
(int x,int y)->x+y;

四、常用的函数式接口

首先我们要知道的是lamda表达式的引入是为了什么,是为了解决经常new对象的问题,解决使用匿名内部类的问题而产生的所以我们先看一下两者在使用上的区别

public class test {public static void main(String[] args) {//匿名内部类的方法startThread(new Runnable() {@Overridepublic void run() {System.out.println("线程启动了" + Thread.currentThread().getName());}});startThread(()->{System.out.println("线程启动"+Thread.currentThread().getName());});}public static void startThread(Runnable r){Thread thread = new Thread(r);thread.start();}
}

从上面的代码上我们可以看出使用lamda表达式写出了的代码要比使用匿名内部类的方法便捷很多

Java8在java.util.function包下预定义了大量的函数数式接口供我们使用。

  • Supplier接口
  • Consumer接口
  • Predicate接口
  • Function接口

4.1、Supplier接口

Supplier:包含一个无参的方法

  • T get():获得结果
  • 该方法不需要参数,它会按照某种实现逻辑(由Lambda表达式实现)返回一个数据。
  • Supplier接口也称为生产型接口,如果我们指定了接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据供我们使用。

示例一

import java.util.function.Supplier;public class test {public static void main(String[] args) {Supplier<String> supplier=()->{return "ltx";};String s = supplier.get();Supplier<Integer> supplier1=()->{return 1;};Integer integer = supplier1.get();System.out.println(s);System.out.println(integer);};
}

示例二

import java.util.function.Supplier;public class test {public static void main(String[] args) {int []arr={1,2,3,4,5,6};int maxvalue=getMax(()->{int a=arr[0];for (int i = 0; i < arr.length; i++) {if(a<arr[i]){a=arr[i];}}return a;});System.out.println(maxvalue);};public static Integer getMax(Supplier<Integer> s){return s.get();}
}

4.2、Consumer接口

Consumer:包含两个方法

  • void accept(T t):对给定的参数执行此操作。
  • default Consumer andThen(Consumer after):返回一个组合的Consumer,依次执行操作,然后执行after操作。
  • Consumer接口也称为消费型接口,它消费的数据的数据类型由泛型指定。

示例一:

import java.util.function.Consumer;public class test {public static void main(String[] args) {Consumer<Integer> integerConsumer = System.out::println;integerConsumer.accept(1);Consumer<String> stringConsumer = name -> System.out.println(name);stringConsumer.accept("ltx");}
}

示例二:

package com.test10;import java.util.function.Consumer;public class ConsumerTest {public static void main(String[] args) {String[] arr={"唐青枫,20","曲无忆,21","离玉堂,22","叶知秋,23"};printInfo(arr,(String str)->{String name=str.split(",")[0];System.out.print("姓名:"+name);},(String str)->{int age=Integer.parseInt(str.split(",")[1]);System.out.println(",年龄:"+age);});}private static void printInfo(String[] arr, Consumer<String> con1, Consumer<String> con2){for(int i=0;i<arr.length;i++){con1.andThen(con2).accept(arr[i]);}}
}

4.3、Predicate接口

Predicate:常用的四个方法:

  • boolean test(T t):对给定的参数进行判断(判断逻辑由Lambda表达式实现),返回一个布尔值。
  • default Predicate negate():返回一个逻辑的否定,对应逻辑非。
  • default Predicate and(Predicate other):返回一个组合判断,对应短路与。
  • default Predicate or(Predicate other):返回一个组合判断,对应短路或。
  • Predicate接口通常用于判断参数是否满足指定的条件。
package com.test12;import java.util.function.Predicate;public class Demo {public static void main(String[] args) {//Lambda表达式
//        boolean b=checkString("Hello",(String str)->{
//            return str.length()>8;
//        });boolean b=checkString("Hello",str->str.length()>8);System.out.println(b);System.out.println("****************************");b=checkString1("Hello",str->str.length()>8);System.out.println(b);}private static boolean checkString(String str, Predicate<String> pre){return pre.test(str);}private static boolean checkString1(String str,Predicate<String> pre){
//        return !pre.test(str);//上一句等价于return pre.negate().test(str);}
}

4.4、Function接口

Function:常用的两个方法

  • R apply(T t):将此函数应用于给定的参数。
  • default Function andThen(Function after):返回一个组合函数,首先将该函数应用于输入,然后将after函数应用于结果。
  • Function:接口通常用于对参数进行处理,转换(处理逻辑由Lambda表达式实现),然后返回一个新的值。

示例

import java.util.function.Function;public class test {public static void main(String[] args) {convert("666", Integer::parseInt);convert(666, String::valueOf);convert("666", Integer::parseInt, String::valueOf);}private static void convert(String s, Function<String,Integer> fun){int i=fun.apply(s);System.out.println(i);}private static void convert(Integer i,Function<Integer,String> fun){String s=fun.apply(i);System.out.println(s);}private static void convert(String s,Function<String,Integer> fun1,Function<Integer,String> fun2){
//        int i=fun1.apply(s);
//        String str=fun2.apply(i);String str=fun1.andThen(fun2).apply(s);System.out.println(str);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/291799.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Netty Review - Netty与Protostuff:打造高效的网络通信

文章目录 概念PrePomServer & ClientProtostuffUtil 解读测试小结 概念 Pre 每日一博 - Protobuf vs. Protostuff&#xff1a;性能、易用性和适用场景分析 Pom <dependency><groupId>com.dyuproject.protostuff</groupId><artifactId>protostuff-…

打破Tomcat中的双亲委派机制:探讨与实践

目录 引言 1. 双亲委派机制概述 2. 打破双亲委派机制的场景 3. Tomcat中的类加载器体系 4. 打破双亲委派机制的方法 4.1 在catalina.properties中配置common.loader 4.2 在META-INF/context.xml中配置Loader元素 4.3 编写自定义的类加载器 5. 潜在的问题与解决方案 5…

Android13 Wifi启动流程分析

Android13 Wifi启动流程分析 文章目录 Android13 Wifi启动流程分析一、正常开关wifi 启动流程1、WifiManager2、WifiServiceImpl3、ActiveModeWarden4、ConcreteClientModeManager5、WifiNative6、WifiVendorHal7、HalDeviceManager8、wifi.cpp 二、重启设备时自动开启wifi流程…

关于LayUI弹出层表单提交两次问题

在弹出层点击 注册 按钮表单会提交两次 但是在单独页面点击是正常的 经过排查发现&#xff0c;问题在于主页面和注册页面重复引用了layui.js&#xff0c;页面要被渲染两次 <script src"../layui/layui.js"></script>

【IntelliJ IDEA】打开项目Git突然无法识别解决方案

这个问题也是我今天突然偶尔遇到的&#xff0c;当时没在意&#xff0c;项目打开之后又关闭&#xff0c;后来很久才又打开&#xff0c;发现项目明明有git版本控制的&#xff0c;咋突然开发工具右下角没有标识了&#xff0c;然后检查了一下git配置还报错了。 其实从图上我们可以看…

Debian在升级过程中报错

当我们在升级的过程中出现如下报错信息 报错信息如下所示&#xff1a; The following signatures couldnt be verified because the public key is not available: NO_PUBKEY ED444FF07D8D0BF6 W: GPG error: http://mirrors.jevincanders.net/kali kali-rolling InRelease: …

使用VSC从零开始Vue.js——备赛笔记——2024全国职业院校技能大赛“大数据应用开发”赛项——任务3:数据可视化

使用Visual Studio Code&#xff08;VSC&#xff09;进行Vue开发非常方便&#xff0c;下面是一些基本步骤&#xff1a; 一、下载和安装Vue 官网下载地址Download | Node.js Vue.js是基于Node.js的&#xff0c;所以首先需要安装Node.js&#xff0c;官网下载地址&#xff1a;No…

jetbrains idea 报错 java.lang.ClassNotFoundException 之后自动搜索包导入包

-- 搜索类所在的包 导入包 搜索包 mac环境 pom中右键或者 cmdn

利用ffmpeg cv2取h265码流视频(转换图片灰屏问题解决)

利用海康威视相机拍出来的视频是H265格式的&#xff0c;相比于常规的H264编码&#xff0c;压缩率更高&#xff0c;但因此如果直接用正常取流方法读取&#xff0c;会出现无法读取的情况 1. 如图h265码流取出图片为灰屏 2 、解决灰屏问题 import subprocess import cv2# 将h265流…

Pooling方法总结(语音识别)

Pooling layer将变长的frame-level features转换为一个定长的向量。 1. Statistics Pooling 链接&#xff1a;http://danielpovey.com/files/2017_interspeech_embeddings.pdf The default pooling method for x-vector is statistics pooling. The statistics pooling laye…

node.js mongoose index(索引)

目录 简介 索引类型 单索引 复合索引 文本索引 简介 在 Mongoose 中&#xff0c;索引&#xff08;Index&#xff09;是一种用于提高查询性能的数据结构&#xff0c;它可以加速对数据库中文档的检索操作 索引类型 单索引、复合索引、文本索引、多键索引、哈希索引、地理…

【单调栈】LeetCode2334:元素值大于变化阈值的子数组

作者推荐 map|动态规划|单调栈|LeetCode975:奇偶跳 涉及知识点 单调栈 题目 给你一个整数数组 nums 和一个整数 threshold 。 找到长度为 k 的 nums 子数组&#xff0c;满足数组中 每个 元素都 大于 threshold / k 。 请你返回满足要求的 任意 子数组的 大小 。如果没有这…