【今日】
昨天是段历史,明天是个谜团,而今天是天赐的礼物
lambda就是数学中的“ λ ”的读音,lambda表达式是基于演算而得名的,因为lambda抽象(lambdabstraction)表示一个匿名的函数,于是开发语言也将lambda表达式用来表示匿名函数,也就是没有函数名字的函数。C#、Python,甚至是C++都有lambda表达式语法。为了提高开发者的开发效率,并照顾“跨语言”开发者的开发习惯,Java语言也加入了lambda表达式。流处理是Java程序中一种重的数据处理手段,它用少量的代码便可以执行复杂的数据过滤、映射、查找和收集等功能。
这里主要学习Lambda表达式,下节学习流处理。
目录
一 Lambda表达式
1.1lambda表达式简介
1.2lambda表达式实现函数式接口
二 方法的引用
1.引用静态方法
2.引用成员方法
3.引用构造方法
4.引用带泛型的方法 (了解)
三 Fuction接口
lambda表达式可以用非常少的代码实现抽象方法。lambda表达式不能独立执行,因此必须实现函数式接口,并且会返回一个函数式接口 。lambda表达式语法格式如下:
()->结果表达式 参数 ->结果表达式 (参数1,参数2,...参数n)->结果表达式
第1行实现无参方法,单独写一对圆括号表示方法无参数,操作符右侧的结果表达式表示方
法的返回值。
第2行实现只有一个参数的方法,参数可以写在圆括号里,或者不写圆括号。
第3行实现多参数的方法,所有参数按顺序写在圆括号里,且圆括号不可以省略。
lambda表达式也可以实现复杂方法,将操作符右侧的结果表达式换成代码块即可,语法格式如下:()->{代码块} 参数 ->{代码块} (参数1,参数2,...参数n)->{代码块}
第1行实现无参方法,方法体是操作符右侧代码块。
第2行实现只有一个参数的方法,方法体是操作符右侧代码块。
第3行实现多参数的方法,方法体是操作符右侧代码块。如果将lambda表达式的功能归纳总结,可以将lambda表达式语法用如下方式理解:
() -> {代码块}
这个方法 按照 这样的代码来实现
lambda表达式可以实现函数式接口(函数式接口)
函数式接口指的是仅包含一个抽象方法的接口,接口中的方法简单明了地说明了接口的用途,如线程接口Runnable、动作事件监听接口ActionListener等。开发者可以创建自定义的函数式接口,例如:interface MyInterface [ void method();
如果接口中包含一个以上的抽象方法,则不符合函数式接口的规范,这样的接口不能用lambda表医 达式创建匿名对象。本章内容中所有被lambda表达式实现的接口均为函数式接口。
1.lambda表达式实现无参抽象方法
️️️很多函数式接口的描放方法是无参数的,如线程接口 Rumable接口只有一个un0方法,这段。参抽象方法在lambda表达式中使用“()”表示。
【代码示例】
interface GameInterface{//创建函数式接口
String Star();
}
public class Dome{
public static void main(String[] args) {
GameInterface s = new GameInterface() {//匿名类
public String Star() {
return "王者启动";
}
};
System.out.println(s.Star());
GameInterface pi=()->"原神启动";//lambda式实现
System.out.println(pi.Star());
}
}
【运行结果】
2.lambda表达式实现有参抽象方法
️️️抽象方法中有一个或多个参数的函数式接口也是很常见的,lambda表达式中可以用“(al,a2,a3)“的方法表示有参抽象方法,圆括号里标识符对应抽象方法的参数。如果抽象方法中只有一个参数lambda表达式则可以省略圆括号。
【代码示例】
interface GameInterface{//创建函数式接口
int add(int a,int b);
}
public class Dome{
public static void main(String[] args) {
GameInterface pi=(x,y)->{
return x+y;
};
System.out.println("相加结果:");
System.out.println(pi.add(2,9));
}
}
【运行结果】
3.lambda表达式使用代码块
当函数式接口的抽象方法需要实现复杂逻辑而不是返回一个简单的表达式的话,就需要在lambda表达式中使用代码块。lambda表达式会自动判断返回值类型是否符合抽象方法的定义。
【代码示例】
import java.util.Scanner;
interface chorkInterface{//创建函数式接口
String score(int a);
}
public class Dome{
public static void main(String[] args) {
chorkInterface pi = (a)->{
if(a>=90&&a<=100) {
return "你真牛逼";
}else if(a>=80&&a<90) {
return "比较厉害";
}else if(a>=60&&a<80) {
return "一般一般";
}else if(a>=0&&a<60) {
return "胡求搞";
}else {
return "骗人安?";
}
};
Scanner sc = new Scanner(System.in);
System.out.println("请输入成绩:");
int b = sc.nextInt();
System.out.println(pi.score(b));
}
}
【运行结果】
️️️ lambda表达式还添加了一类新语法,用来引用方法,也就是说方法也可以作为一个对象被调用。根据不同的方法类型,方法的引用包括引用静态方法、引用成员方法和引用构造方法等。
引用静态方法的语法如下:
类名:静态方法名
这个语法中出现了一个新的操作符“::”,这是由两个英文冒号组成的操作符,冒号之间没有空格。这个操作符左边表示方法所属的类名,右边是方法名。需要注意的是,这个语法中方法名是没有圆括号的。
【代码示例】
interface A{//创建一个接口A
int nod(int a,int b);//定义了一个抽象方法
}
class B{//实现某个方法的类
static int add(int x,int y) {
return (x+y);
}
}
public class Dome{
public static void main(String[] args) {
A a = B::add;//引用B类的静态方法
System.out.println(a.nod(8, 9));
}
}
【运行结果】
引用成员方法的语法如下:、
(非静态成员方法)
对象名::成员方法名
与引用静态方法语法不同,这里操作符左侧必须是一个对象名,而不是类名。这种语法也可以达到抽象方法按照类成员方法逻辑来实现的目的。
【代码示例】
interface A{//创建一个接口A
int method(int x,int y);//定义了一个抽象方法
}
class B{//实现某个方法的类
int add(int x,int y) {
return (x+y);
}
}
public class Dome{
public static void main(String[] args) {
B b = new B();//创建了B类的对象
A a = b::add;//引用非静态方法
System.out.println(a.method(5,8));
}
}
【运行结果】
引用构造方法的语法如下:
类名::new
【代码示例】
interface A{//创建一个接口A
Dome Kun();//定义了一个抽象方法
}
class B{//实现某个方法的类
static int add(int x,int y) {
return (x+y);
}
Dome getDome() {
return new Dome();
}
}
public class Dome{
public static void main(String[] args) {
B b = new B();//创建了B类的对象
A a = b::getDome;
A a2= Dome::new;//引用构造方法
System.out.println(b.getDome());
System.out.println(a2.Kun());
}
}
【运行结果】
“::"操作符支持引用带泛型的方法。除方法以外,“::"操作符也支持引用带泛型的类。
【代码示例】
interface A{//创建一个接口A
int mothed(T t);
}
class B{//实现某个方法的类
static int mothed(T t) {
return t.hashCode();
}
}
public class Dome{
public static void main(String[] args) {
A a = B::mothed;
String b="你好";
System.out.println(b+"的hashCode为:");
System.out.println(a.mothed(b));
}
}
【运行结果】
在此之前的所有实例中,想要使用lambda表达式都需要先创建或调用已有的函数式接口,java.util.function包已经提供了很多预定义函数式接口,就是没有实现任何功能,仅用来封装lambd表达式的对象。该包中最常用的接口是Function
T:被操作的类型,可以理解为方法参数类型。
R:操作结果类型,可以理解为方法的返回类型。
Function接口是函数式接口,所以只有一个抽象方法,但是Function接口还提供了3个已实现的方法以方便开发者对函数逻辑进行更深层的处理。如表所示
【代码示例】
import java.util.function.Function;
public class Dome{
public static void main(String[] args) {
Integer[] ip = {196,261,1,1};//ip数组
Function f = (n)->{
/*创建Function接口对象,参数类型是Integer[],
* 返回值类型是String
*/
StringBuilder s = new StringBuilder();//创建字符序列
for(int i=0;i
这里用的StringBuilder以及方法append(),deleteCharAt()再前面的字符串知识讲过:
http://t.csdn.cn/xHYDN
【运行结果】
compose与andThen方法
【代码示例】
import java.util.function.Function;
public class Dome{
public static void main(String[] args) {
Function function=Function.identity();//创建了空的function的对象
String result = function.apply("启动");
System.out.println(result);
Function before = (n)->{
return "原神"+n;
};
result = function.compose(before).apply("启动");
/*先将apply("启动")中的参数“启动”传入before中当作参数n处理,然后将compose得到结果作为
* 参数传给apply进行输出
*/
System.out.println(result);
Function after = (n)->{
return n+",王者启动!";
};
result = function.compose(before).andThen(after).apply("启动");
/*先将apply("启动")中的参数“启动”传入before中当作参数n处理
*然后将compose得到结果传给apply,然后在将此结果传给andThen,得到新的结果
*最后再给apply
*/
System.out.println(result);
}
}
【运行结果】