​Lambda表达式详解​-初遇者-很细

news/2024/12/6 20:12:31/

目录

Lambda简介

对接口的要求

Lambda 基础语法

Lambda 语法简化

Lambda 表达式常用示例

lambda 表达式引用方法

构造方法的引用

lambda 表达式创建线程

遍历集合

删除集合中的某个元素

集合内元素的排序

Lambda 表达式中的闭包问题


Lambda简介

Lambda 表达式是 JDK8 的一个新特性,可以取代大部分的匿名内部类,写出更优雅的 Java 代码,尤其在集合的遍历和其他集合操作中,可以极大地优化代码结构。

JDK 也提供了大量的内置函数式接口供我们使用,使得 Lambda 表达式的运用更加方便、高效。

对接口的要求

虽然使用 Lambda 表达式可以对某些接口进行简单的实现,但并不是所有的接口都可以使用 Lambda 表达式来实现。Lambda 规定接口中只能有一个需要被实现的方法,不是规定接口中只能有一个方法

jdk 8 中有另一个新特性:default, 被 default 修饰的方法会有默认实现,不是必须被实现的方法,所以不影响 Lambda 表达式的使用。

@FunctionalInterface

修饰函数式接口的,要求接口中的抽象方法只有一个。 这个注解往往会和 lambda 表达式一起出现。

Lambda 基础语法

我们这里给出六个接口,后文的全部操作都利用这六个接口来进行阐述。

/**多参数无返回*/@FunctionalInterface
public interface NoReturnMultiParam {void method(int a, int b);
}/**无参无返回值*/@FunctionalInterface
public interface NoReturnNoParam {void method();
}/**一个参数无返回*/@FunctionalInterface
public interface NoReturnOneParam {void method(int a);
}/**多个参数有返回值*/@FunctionalInterface
public interface ReturnMultiParam {int method(int a, int b);
}/*** 无参有返回*/
@FunctionalInterface
public interface ReturnNoParam {int method();
}/**一个参数有返回值*/
@FunctionalInterface
public interface ReturnOneParam {int method(int a);
}

语法形式为 () -> {},其中 () 用来描述参数列表,{} 用来描述方法体,-> 为 lambda运算符 ,读作(goes to)。

import lambda.interfaces.*;
public class Test1 {public static void main(String[] args) {//无参无返回 定义NoReturnNoParam noReturnNoParam = () -> {System.out.println("NoReturnNoParam");};//调用noReturnNoParam.method();//一个参数无返回NoReturnOneParam noReturnOneParam = (int a) -> {System.out.println("NoReturnOneParam param:" + a);};noReturnOneParam.method(6);//多个参数无返回NoReturnMultiParam noReturnMultiParam = (int a, int b) -> {System.out.println("NoReturnMultiParam param:" + "{" + a +"," + + b +"}");};noReturnMultiParam.method(6, 8);//无参有返回值ReturnNoParam returnNoParam = () -> {System.out.print("ReturnNoParam");return 1;};int res = returnNoParam.method();System.out.println("return:" + res);//一个参数有返回值ReturnOneParam returnOneParam = (int a) -> {System.out.println("ReturnOneParam param:" + a);return 1;};int res2 = returnOneParam.method(6);System.out.println("return:" + res2);//多个参数有返回值ReturnMultiParam returnMultiParam = (int a, int b) -> {System.out.println("ReturnMultiParam param:" + "{" + a + "," + b +"}");return 1;};int res3 = returnMultiParam.method(6, 8);System.out.println("return:" + res3);}}

Lambda 语法简化

我们可以通过观察以下代码来完成代码的进一步简化,写出更加优雅的代码。

import lambda.interfaces.*;
public class Test2 {public static void main(String[] args) {//1.简化参数类型,可以不写参数类型,但是必须所有参数都不写NoReturnMultiParam lamdba1 = (a, b) -> {System.out.println("简化参数类型");};lamdba1.method(1, 2);//2.简化参数小括号,如果只有一个参数则可以省略参数小括号NoReturnOneParam lambda2 = a -> {System.out.println("简化参数小括号");};lambda2.method(1);//3.简化方法体大括号,如果方法条只有一条语句,则可以省略方法体大括号NoReturnNoParam lambda3 = () -> System.out.println("简化方法体大括号");lambda3.method();//4.如果方法体只有一条语句,并且是 return 语句,则可以省略方法体大括号ReturnOneParam lambda4 = a -> a+3;System.out.println(lambda4.method(5));ReturnMultiParam lambda5 = (a, b) -> a+b;System.out.println(lambda5.method(1, 1));}}


 

Lambda 表达式常用示例

lambda 表达式引用方法

有时候我们不是必须要自己重写某个匿名内部类的方法,我们可以可以利用 lambda表达式的接口快速指向一个已经被实现的方法。

语法

方法归属者::方法名 静态方法的归属者为类名,普通方法归属者为对象

public class Exe1 {public static void main(String[] args) {ReturnOneParam lambda1 = a -> doubleNum(a);System.out.println(lambda1.method(3));//lambda2 引用了已经实现的 doubleNum 方法ReturnOneParam lambda2 = Exe1::doubleNum;System.out.println(lambda2.method(3));Exe1 exe = new Exe1();//lambda4 引用了已经实现的 addTwo 方法ReturnOneParam lambda4 = exe::addTwo;System.out.println(lambda4.method(2));}/*** 要求* 1.参数数量和类型要与接口中定义的一致* 2.返回值类型要与接口中定义的一致*/public static int doubleNum(int a) {return a * 2;}public int addTwo(int a) {return a + 2;}}

构造方法的引用

一般我们需要声明接口,该接口作为对象的生成器,通过 类名::new 的方式来实例化对象,然后调用方法返回对象。

interface ItemCreatorBlankConstruct {Item getItem();
}interface ItemCreatorParamContruct {Item getItem(int id, String name, double price);
}public class Exe2 {public static void main(String[] args) {ItemCreatorBlankConstruct creator = () -> new Item();Item item = creator.getItem();ItemCreatorBlankConstruct creator2 = Item::new;Item item2 = creator2.getItem();ItemCreatorParamContruct creator3 = Item::new;Item item3 = creator3.getItem(112, "鼠标", 135.99);}}

lambda 表达式创建线程

我们以往都是通过创建 Thread 对象,然后通过匿名内部类重写 run() 方法,一提到匿名内部类我们就应该想到可以使用 lambda 表达式来简化线程的创建过程。

    Thread thread=new Thread( new Runnable() {@Overridepublic void run() {}});//简化后Thread t = new Thread(() -> {for (int i = 0; i < 10; i++) {System.out.println(2 + ":" + i);}});t.start();

遍历集合

我们可以调用集合的 public void forEach(Consumer<? super E> action) 方法,通过 lambda 表达式的方式遍历集合中的元素。以下是 Consumer 接口的方法以及遍历集合的操作。Consumer 接口是 jdk 为我们提供的一个函数式接口。

    @FunctionalInterfacepublic interface Consumer<T> {void accept(T t);//....}ArrayList<Integer> list = new ArrayList<>();Collections.addAll(list, 1,2,3,4,5);//lambda表达式 方法引用list.forEach(System.out::println);list.forEach(element -> {if (element % 2 == 0) {System.out.println(element);}});

删除集合中的某个元素

我们通过public boolean removeIf(Predicate<? super E> filter)方法来删除集合中的某个元素,Predicate 也是 jdk 为我们提供的一个函数式接口,可以简化程序的编写。

      ArrayList<Item> items = new ArrayList<>();items.add(new Item(11, "小牙刷", 12.05 ));items.add(new Item(5, "日本马桶盖", 999.05 ));items.add(new Item(7, "格力空调", 888.88 ));items.add(new Item(17, "肥皂", 2.00 ));items.add(new Item(9, "冰箱", 4200.00 ));items.removeIf(ele -> ele.getId() == 7);//通过 foreach 遍历,查看是否已经删除items.forEach(System.out::println);

集合内元素的排序

在以前我们若要为集合内的元素排序,就必须调用 sort 方法,传入比较器匿名内部类重写 compare 方法,我们现在可以使用 lambda 表达式来简化代码。

        ArrayList<Item> list = new ArrayList<>();list.add(new Item(13, "背心", 7.80));list.add(new Item(11, "半袖", 37.80));list.add(new Item(14, "风衣", 139.80));list.add(new Item(12, "秋裤", 55.33));//通常写法/*list.sort(new Comparator<Item>() {@Overridepublic int compare(Item o1, Item o2) {return o1.getId()  - o2.getId();}});*///简化写法list.sort((o1, o2) -> o1.getId() - o2.getId());System.out.println(list);

Lambda 表达式中的闭包问题

这个问题我们在匿名内部类中也会存在,如果我们把下例注释放开会报错,告诉我 num 值是 final 不能被改变。这里我们虽然没有标识 num 类型为 final,但是在编译期间虚拟机会帮我们加上 final 修饰关键字。

import java.util.function.Consumer;
public class Main {public static void main(String[] args) {int num = 10;Consumer<String> consumer = ele -> {System.out.println(num);};//num = num + 2;consumer.accept("hello");}
}


http://www.ppmy.cn/news/89631.html

相关文章

详解Java项目安全方向解决方案

Java作为一种广泛使用的编程语言&#xff0c;广泛应用于各种企业级应用程序的开发中。但是&#xff0c;Java应用程序被黑客攻击是一种常见现象&#xff0c;因此保障Java应用程序的安全至关重要。 在Java项目开发中&#xff0c;安全方向主要包括以下几个方面&#xff1a;认证、…

C#使用HTTP发送POST Params传参值为Json字符串解决

Post&#xff1a;方法 public static string Post(string url, Dictionary<string, string> dic) { string tempMessage ""; System.Net.WebClient WebClientObj new System.Net.WebClient(); System.Collectio…

VR全景智慧城市:构筑未来城市的数字化大融合

引言&#xff1a; 现代城市正处于数字化时代的浪潮之中&#xff0c;而在这个数字化浪潮中&#xff0c;VR全景智慧城市正以令人瞩目的方式崭露头角。随着虚拟现实&#xff08;VR&#xff09;技术的不断进步和智慧城市的发展需求&#xff0c;VR全景智慧城市作为数字技术与城市发展…

【TI毫米波雷达笔记】IWR6843AOPEVM-G+DCA1000EVM的mmWave Studio数据读取、配置及避坑

【TI毫米波雷达笔记】IWR6843AOPEVM-GDCA1000EVM的mmWave Studio数据读取、配置及避坑 硬件方面连接好以后 就可以打开mmWave Studio了 配置 如果硬件配置成功 则可以通过mmWave Studio的Output看到配置信息 按照如图步骤 在radar api里面一步步来操作 其中 RS232选择波特率…

国家信息安全测评信息安全服务资质证书(安全工程类一级)申请条件

中国信息安全测评中心&#xff08;以下简称CNITSEC&#xff09;是经中央批准成立的国家信息安全权威测评机构&#xff0c;职能是开展信息安全漏洞分析和风险评估工作&#xff0c;对信息技术产品、信息系统和工程的安全性进行测试与评估。对信息安全服务和人员的资质进行审核与评…

内网渗透(八十)之搭建额外域控

搭建额外域控 我们在之前搭建完成Windows Server 2012 R2 域控的基础上搭建一个额外的域控。多个域控的好处在于,当其中有域控出现了故障,仍然能够由其他域控来提供服务。选择一台Windows Server 2012 R2 服务器作为额外域控,主机名为DC2. 首先在DC2上配置IP地址为192.168…

【Lychee图床】本地电脑搭建私人图床,公网远程访问

文章目录 1.前言2. Lychee网站搭建2.1. Lychee下载和安装2.2 Lychee网页测试2.3 cpolar的安装和注册 3.本地网页发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4.公网访问测试5.结语 转发自CSDN风浪越大%鱼越贵的文章&#xff1a;Lychee图床 - 本地配置属于自己的相册管理系统并远…

Spring源码阅读:Spring事务传播特性

一、概述 我们平常工作中经常会听到事务的传播级别&#xff0c;但是使用中基本不会太调整这个事务传播级别&#xff0c;因为没什么业务场景需要我们这么做&#xff0c;只需要使用原有的事务传播级别即可解决95%的业务场景。但是为了那5%的业务场景&#xff0c;我们还是还要学习…