函数式编程
创始人
2024-01-30 19:32:34

Lambda表达式介绍

Lambda简介

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

在Java语言中,可以为变量赋予一个值:

 能否把一个代码块赋给一变量吗?

 在Java 8之前,这个是做不到的。但是Java 8问世之后,利用Lambda特性,就可以做到了。

 甚至我们可以让语法变得更简洁。

 在Java 8里面,所有的Lambda的类型都是一个接口,而Lambda表达式本身,也就是”那段代码“,需要是这个接口的实现。这是我认为理解Lambda的一个关键所在,简而言之就是,Lambda表达式本身就是一个接口的实现。直接这样说可能还是有点让人困扰,我们继续看看例子。我们给上面的aBlockOfCode加上一个类型:

 这种只有一个接口函数需要被实现的接口类型,我们叫它“函数式接口”。为了避免后来的人在这个接口中增加接口函数导致其有多个接口函数需要被实现,变成"非函数接口”,我们可以在这个上面加上一个声明@FunctionalInterface, 这样别人就无法在里面添加新的接口函数了。

Lambda作用

最直观的作用就是使得代码变得异常简洁。

 接口要求

虽然使用 Lambda 表达式可以对某些接口进行简单的实现,但并不是所有的接口都可以使用 Lambda 表达式来实现。Lambda 规定接口中只能有一个需要被实现的方法,不是规定接口中只能有一个方法。 jdk 8 中有另一个新特性:default, 被 default 修饰的方法会有默认实现,不是必须被实现的方法,所以不影响 Lambda 表达式的使用。 @FunctionalInterface注解作用 @FunctionalInterface标记在接口上,“函数式接口”是指仅仅只包含一个抽象方法的接口。 Lambda表达式语法

 

语法结构

(parameters) -> expression
或
(parameters) ->{ statements;}
语法形式为 () -> {}: () 用来描述参数列表,如果有多个参数,参数之间用逗号隔开,如果没有参数,留空即可; -> 读作(goes to),为 lambda运算符 ,固定写法,代表指向动作; {} 代码块,具体要做的事情,也就是方法体内容; Lambda表达式的重要特征 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。 Lambda案例
// 1. 不需要参数,返回值为 5  
() -> 5  // 2. 接收一个参数(数字类型),返回其2倍的值  
x -> 2 * x  // 3. 接受2个参数(数字),并返回他们的差值  
(x, y) -> x – y  // 4. 接收2个int型整数,返回他们的和  
(int x, int y) -> x + y  // 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s)


Lambda表达式入门案例

定义函数接口

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

实现函数接口

public static void main(String[] args) {/*** 无返回值,无参数*/NoReturnNoParam noReturnNoParam = ()->{System.out.println("NoReturnNoParam");   };noReturnNoParam.method();/*** 无返回值,有一个参数*/NoReturnOneParam noReturnOneParam = (int a)->{System.out.println("NoReturnOneParam "+a);};noReturnOneParam.method(10);/*** 无返回值,有多个参数*/NoReturnMultiParam noReturnMultiParam = (int a, int b)->{System.out.println("NoReturnMultiParam "+a+"\t"+b);};noReturnMultiParam.method(10,20);/*** 有返回值,无参数*/ReturnNoParam returnNoParam = ()->{System.out.print("ReturnNoParam ");return 10;};System.out.println(returnNoParam.method());/*** 有返回值,有一个参数*/ReturnOneParam returnOneParam = (int a)->{System.out.print("ReturnOneParam ");return a;};System.out.println(returnOneParam.method(10));/*** 有返回值,有多个参数*/ReturnMultiParam returnMultiParam = (int a ,int b)->{System.out.print("ReturnMultiParam ");return a+b;};System.out.println(returnMultiParam.method(10, 20));
}
Lambda语法简化
/*** 无返回值,无参数*//* NoReturnNoParam noReturnNoParam = ()->{       System.out.println("NoReturnNoParam");};*//*** 简化版*/NoReturnNoParam noReturnNoParam = ()-> System.out.println("NoReturnNoParam");noReturnNoParam.method();/*** 无返回值,有一个参数*//* NoReturnOneParam noReturnOneParam = (int a)->{System.out.println("NoReturnOneParam "+a);};*//*** 简化版*/NoReturnOneParam noReturnOneParam = a ->
System.out.println("NoReturnOneParam "+a);noReturnOneParam.method(10);/*** 无返回值,有多个参数*//* NoReturnMultiParam noReturnMultiParam = (int a, int b)->{System.out.println("NoReturnMultiParam "+a+"\t"+b);};*/    NoReturnMultiParam noReturnMultiParam = (a,b)-> System.out.println("NoReturnMultiParam "+a+"\t"+b);noReturnMultiParam.method(10,20);/*** 有返回值,无参数*//* ReturnNoParam returnNoParam = ()->{System.out.print("ReturnNoParam ");return 10;};*//*** 简化版*/ReturnNoParam returnNoParam = ()->10+20;System.out.println(returnNoParam.method());/*** 有返回值,有一个参数*//* ReturnOneParam returnOneParam = (int a)->{System.out.print("ReturnOneParam ");return a;};*//**** 简化版*/ReturnOneParam returnOneParam = a->a;System.out.println(returnOneParam.method(10));。/*** 有返回值,有多个参数*//*ReturnMultiParam returnMultiParam = (int a ,int b)->{System.out.print("ReturnMultiParam ");return a+b;};*//*** 简化版*/ReturnMultiParam returnMultiParam = (a ,b)- >a+b;System.out.println(returnMultiParam.method(10,20));}

Lambda表达式的使用 Lambda表达式引用方法 有时候我们不是必须使用Lambda的函数体定义实现,我们可以利用 lambda表达式指向一个已经存在的方法作为抽象方法的实现。 要求 ● 参数的个数以及类型需要与函数接口中的抽象方法一致 ● 返回值类型要与函数接口中的抽象方法的返回值类型一致。 语法 方法归属者::方法名 静态方法的归属者为类名,非静态方法归属者为该对象的引用。 案例
/*** 无返回值,无参数*/
@FunctionalInterface
interface NoReturnNoParam{void method();
}
/*** 无返回值,有一个参数*/
@FunctionalInterface
interface NoReturnOneParam{void method(int a);
}
/*** 无返回值,有多个参数*/
@FunctionalInterface
interface NoReturnMultiParam{void method(int a,int b);
}/*** 有返回值,无参数*/
@FunctionalInterface
interface ReturnNoParam{int method();
}
/*** 有返回值,有一个参数*/
@FunctionalInterface
interface ReturnOneParam{int method(int a);
}
/*** 有返回值,有多个参数*/
@FunctionalInterface
interface ReturnMultiParam{int method(int a,int b);
}
public class Test {public static void main(String[] args) {/*** 无返回值,无参数*//* NoReturnNoParam noReturnNoParam = ()->{System.out.println("NoReturnNoParam");        };*//*** 简化版*/NoReturnNoParam noReturnNoParam = ()->
System.out.println("NoReturnNoParam");noReturnNoParam.method();/*** 无返回值,有一个参数*//* NoReturnOneParam noReturnOneParam = (int a)->{System.out.println("NoReturnOneParam "+a);};*//*** 简化版*/NoReturnOneParam noReturnOneParam = a - > System.out.println("NoReturnOneParam "+a);noReturnOneParam.method(10);/*** 无返回值,有多个参数*//* NoReturnMultiParam noReturnMultiParam = (int a, int b)->{System.out.println("NoReturnMultiParam "+a+"\t"+b);};*/        NoReturnMultiParam noReturnMultiParam = (a,b)-> System.out.println("NoReturnMultiParam "+a+"\t"+b);noReturnMultiParam.method(10,20);/*** 有返回值,无参数*//* ReturnNoParam returnNoParam = ()->{System.out.print("ReturnNoParam ");return 10;};*//*** 简化版*/ReturnNoParam returnNoParam = ()- >10+20;System.out.println(returnNoParam.method());/*** 有返回值,有一个参数*//* ReturnOneParam returnOneParam = (int a)->{System.out.print("ReturnOneParam
");return a;};*//**** 简化版*/        ReturnOneParam returnOneParam = a->a;System.out.println(returnOneParam.method(10));/*** 有返回值,有多个参数*//*ReturnMultiParam returnMultiParam = (int a ,int b)->{System.out.print("ReturnMultiParam ");return a+b;};*//*** 简化版*/ReturnMultiParam returnMultiParam = (a ,b)->a+b;System.out.println(returnMultiParam.method(10, 20));}/*** 要求:* 1,参数的个数以及类型需要与函数接口中的抽象方法一致。* 2,返回值类型要与函数接口中的抽象方法的返回值类型一致。* @param a* @return*/public static int doubleNum(int a){return 2*a;}public int addTwo(int a){return a+2;}
}
public class Test2 {public static void main(String[] args) {ReturnOneParam returnOneParam = Test::doubleNum;int value = returnOneParam.method(10);System.out.println(value);Test test = new Test();ReturnOneParam returnOneParam1 = test::addTwo;int value2 = returnOneParam1.method(10);System.out.println(value2);}
}

Lambda表达式创建线程

public class Test3 {    public static void main(String[] args) {System.out.println(Thread.currentThread().getName()+" 开始");new Thread(()->{for(int i=0;i<20;i++){try {Thread.sleep(500);} catch (InterruptedExceptione) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+" "+i);}},"Lambda Thread ").start();System.out.println(Thread.currentThread().getName()+" 结束");}
}

Lambda 表达式中的闭包问题

什么是闭包 闭包的本质就是代码片断。所以闭包可以理解成一个代码片断的引用。在Java中匿名内部类也是闭包的一种实现方式。 在闭包中访问外部的变量时,外部变量必须是final类型,虚拟机会帮我们加上 final 修饰关键字。
public class Test4 {public static void main(String[] args) {final int num  =10;NoReturnNoParam noReturnNoParam = ()->System.out.println(num);noReturnNoParam.method();}
}

常用的函数接口

Consumer接口的使用 Consumer 接口是JDK为我们提供的一个函数式接口,该接口也被称为消费型接口。 遍历集合 我们可以调用集合的 public void forEach(Consumer action) 方法,通过 lambda 表达式的方式遍历集合中的元素。以下是 Consumer 接口的方法以及遍历集合的操作。
public class Test4 {public static void main(String[] args) {List list = new ArrayList<>();list.add("a");list.add("b");list.add("c");list.add("d");list.forEach(System.out::println);}
}

Predicate接口的使用

Predicate 是 JDK 为我们提供的一个函数式接口,可以简化程序的编写。 删除集合中的元素 我们通过public boolean removeIf(Predicate filter)方法来删除集合中的某个元素,
public class Test5 {public static void main(String[] args) {List list = new ArrayList<>();list.add("a");list.add("b");list.add("c");list.add("d");list.removeIf(ele->ele.equals("b"));list.forEach(System.out::println);}
}

Comparator接口的使用

Comparator是 JDK 为我们提供的一个函数式接口,该接口为比较器接口。 元素排序 之前我们若要为集合内的元素排序,就必须调用 sort 方法,传入比较器重写 compare 方法的比较器对象,现在我们还可以使用lambda 表达式来简化代码。
public class Test7 {public static void main(String[] args) {List list = new ArrayList<>();list.add("a");list.add("d");list.add("b");list.add("c");list.sort((o1,o2)->o1.compareTo(o2));list.forEach(System.out::println);}
}

Stream流介绍

Stream流简介

Stream是数据渠道,用于操作数据源所生成的元素序列,它可以实现对集合的复杂操作,例如过滤、排序和映射等。Stream不会改变源对象,而是返回一个新的结果集。

Stream流的生成方式         ● 生成流:通过数据源(集合、数组等)创建一个流。         ● 中间操作:一个流后面可以跟随零个或者多个中间操作,其目的主要是打开流,做出某种程度的数         ● 据过滤/映射,然后返回一个新的流,交给下一个操作使用。         ● 终结操作:一旦执行终止操作,就执行中间的链式操作,并产生结果。 Stream流的常见方法 数据过滤
public class Test8 {public static void main(String[] args) {List list = new ArrayList<>();list.add("oldlu");list.add("oldlin");list.add("kevin");list.add("peter");//多条件and关系list.stream().filter(ele ->
ele.startsWith("o")).filter(ele >ele.endsWith("n")).collect(Collectors.toList()
).forEach(System.out::println);System.out.println("-------------------
-----");//多条件or关系Predicate predicate1 = ele ->
ele.startsWith("o");Predicate predicate2 = ele-
>ele.endsWith("n");list.stream().filter(predicate1.or(predicate2)
).collect(Collectors.toList()).forEach(System.o
ut::println);}
}

数量限制

public class Test9 {public static void main(String[] args) {List list = new ArrayList<>();list.add("oldlu");list.add("oldlin");list.add("kevin");list.add("peter");//limitlist.stream().limit(2).forEach(System.out::println);}
}

元素排序

public class Test10 {public static void main(String[] args) {List list = new ArrayList<>();list.add("b");list.add("c");list.add("a");list.add("d");//升序排序list.stream().sorted(Comparator.naturalOrder()).forEach(System.out::println);System.out.println("---------------");//降序排序list.stream().sorted(Comparator.reverseOrder()).forEach(System.out::println);}
}

相关内容

热门资讯

长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
1秒多少毫秒 1秒等于多少毫秒... 长度单位换算1丈=10尺;1尺=10寸;1寸=10分;1分=10厘;1丈≈3.33米;1尺≈3.33...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
中国电信人工电话多少 中国电信... 当我们在使用中国移动、中国电信和中国联通提供的电信业务时,可能会发生争议。建议直接向服务提供商投诉,...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...