关于对【java中的Lambda表达式】的理解与简述

这篇具有很好参考价值的文章主要介绍了关于对【java中的Lambda表达式】的理解与简述。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【版权声明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权)
https://blog.csdn.net/m0_69908381/article/details/130522535
出自【进步*于辰的博客】

启发博文:《Lambda表达式超详细总结》(转发)。
这是我系统学习Lambda表达式时参考的文章。在下文中,我会引用这篇博文中的一些资源,如:图片、阐述。因为我认为那位前辈总结的很好,我再尽力做也最多如此了。如有侵权,请与我联系!
参考笔记一,P33.8、P43.5;笔记三,P33.1。

注:掌握Lambda表达式,这两个知识是基础:

  1. 匿名内部类,帮助在于理解“ 变式 \color{red}{变式} 变式”,因为最初开发Lambda表达式的目的之一是简化匿名内部类;
  2. 泛型,用于Lambda表达式的“ 扩展 \color{red}{扩展} 扩展”。

1、关于Lambda优化匿名内部类

1.1 内部类

java中内部类分为成员内部类、静态内部类、局部内部类和匿名内部类。

class TestInnerClass {
    // 成员内部类
    class MemberInner {}
	
	// 静态内部类
    static class StaticInner {}

    public static void main(String[] args) {
		// 局部内部类
        class LocalInner {}

        // 匿名内部类
        Runnable run = new Runnable() {
            public void run() {}
        };
        new Thread(run).start();
    }
}

与Lambda表达式相关的只有匿名内部类。

1.2 匿名内部类

示例:

Runnable runa = new Runnable() {
    public void run() {
    	sout "Hello!! CSDN";
    }
};
new Thread(runa).start();

等同于:

class MyRunnable implements Runnable {
    public void run() {
    	sout "Hello!! CSDN";
    }
}
class TestThread {
    public static void main(String[] args) {
        Runnable runa = new MyRunnable();
        new Thread(runa).start();
    }
}

匿名内部类一般有一个特点: 一次性 \color{red}{一次性} 一次性,故这种写法既冗余,又 L O W LOW LOW

使用 L a m b d a 进行优化: \color{red}{使用Lambda进行优化:} 使用Lambda进行优化:

Runnable runa = () -> {
    sout "Hello!! CSDN";
};
new Thread(runa).start();

有什么变化?是不是省去了run()的声明部分。
继续优化。

new Thread(() -> {
    sout "Hello!! CSDN";
}).start();

这就是 “将函数如参数般传递” \color{red}{“将函数如参数般传递”} 将函数如参数般传递。大家先初步了解,继续看。。。

题外话: 题外话: 题外话:
此项的第一个示例中的引用runa,指向 Runnable 接口的匿名内部类(上转),而下文所述的() -> {}和三种引用都可以说是对匿名内部类的简化,但其已不是匿名内部类,其类型是Lambda(一种类型)。
我暂未找到相关资料,就自己验证。看下述示例。

Predicate<Integer> ser1 = new Predicate<Integer>() {
    @Override
    public boolean test(Integer a) {
        return a.equals(0);
    }
};
Class z1 = ser1.getClass();
System.out.println(z1);// class Test2$1
System.out.println(z1.getSimpleName());// ""
System.out.println(z1.getEnclosingClass());// class Test2

Supplier<Integer> ser2 = () -> {
    return 0;
};
z1 = ser2.getClass();
System.out.println(z1);// class Test2$$Lambda$1/1791741888
System.out.println(z1.getSimpleName());// Test2$$Lambda$1/1791741888
System.out.println(z1.getEnclosingClass());// null

具体说明简单又啰嗦,就不赘述,大家只要了解getSimpleName()getEnclosingClass()这两个方法就明白了。如果大家感兴趣,可以看看我对Class<T>类的解析。

2、关于Lambda的优化规范

2.1 准备

从:

Runnable runa = new Runnable() {
    public void run() {
    	sout "Hello!! CSDN";
    }
};
new Thread(runa).start();

优化为:

Runnable runa = () -> {
    sout "Hello!! CSDN";
};
new Thread(runa).start();

难道可以随便写?当然不是。那规范是什么?

在上个例子中,大家有没有注意一个问题? \color{grey}{在上个例子中,大家有没有注意一个问题?} 在上个例子中,大家有没有注意一个问题?
在示例中,有没有run()的声明?没有。因此,Lambda只能优化只有一个抽象方法的接口的匿名内部类,这类接口称之为 函数式接口 \color{green}{函数式接口} 函数式接口(注解是@FunctionalInterface)。

举个例:定义java.lang.Number抽象类的匿名内部类。
这是Number抽象类的源码。
关于对【java中的Lambda表达式】的理解与简述

可见,有4个抽象方法。因此,创建 Number 类的匿名内部类,必须重写这4个抽象方法。即:

new Number() {
    @Override
    public int intValue() {
        return 0;
    }
    @Override
    public long longValue() {
        return 0;
    }
    ......
};

如这般,就无法使用 Lambda 进行优化。

2.2 规范

Lambda 的基础语法:() -> {}

->的左边是圆括号,对应匿名内部类重写的唯一抽象方法的参数列表;右边是花括号,对应方法体。

参数列表: \color{red}{参数列表:} 参数列表:

  1. 若无参,则必须是(),即:() -> {}
  2. 若只有1个参数xx,则可以是(xx)xx,即:(xx) -> {}xx -> {};(注:xx无类型,其名称任意)
  3. 若有2个参数 a 和 b,则必须是(a, b),即:(a, b) -> {}
  4. 举一反三。

方法体: \color{red}{方法体:} 方法体:
由于方法体不用关注方法的声明,故只注意一些 省略规范 省略规范 省略规范

1、 若只有一条语句,可省略分号和花括号。
示例:

new Thread(() -> sout "Hello!! CSDN").start();
// 等同于:
new Thread(() -> {
	sout "Hello!! CSDN";
}).start();

run()无参。

2、 若方法有返回值,且只有一条语句时,可省略分号、花括号和return
示例:

interface SelfInterface {
    double getTrigonometric(double angle);
}

class TestSelf {
    public static void main(String[] args) {
        SelfInterface service = xx -> Math.sin(xx);
        // 等同于:
        SelfInterface service = xx -> {
            return Math.sin(xx);
        };
        
        double radian = service.getRadian(10);
        sout radian;// 打印:-0.5440211108893698
    }
}

2.3 补充说明

以上例为例:
关于对【java中的Lambda表达式】的理解与简述
两个问题: \color{grey}{两个问题:} 两个问题:

  1. JVM如何知道图中红框部分是getTrigonometric()的方法体?
  2. JVM是如何知道参数xx的类型是double?(因为Math.sin()的形参类型是 double)

下图是Math.sin()的API截图:
关于对【java中的Lambda表达式】的理解与简述
解释: \color{red}{解释:} 解释: (以下阐述转载自博文《Lambda表达式超详细总结》)

因为JVM可以通过上下文推断出为何接口实现抽象方法,即 接口推断 \color{purple}{接口推断} 接口推断;以及推断出所实现的相应抽象方法的参数列表(包括形参类型),即 类型推断 \color{brown}{类型推断} 类型推断
简言之,Lambda表达式依赖于上下文环境

3、Java内置函数式接口

3.1 四大核心函数式接口

(此表格引用自启发博文。)

函数式接口 参数类型 返回值类型 说明
Consumer<T>消费型接口 T void 对类型为T的对象应用操作,包含方法:void accept(T t)
Supplier<T>供给型接口 T 返回类型为T的对象,包含方法:T get()
Function<T, R> T R 对类型为T的对象应用操作,并返回类型为R的对象,包含方法:R apply(T t)
Predicate<T>断定型接口 T boolean 断定类型为T的对象是否满足某约束,并返回boolean结果,包含方法:boolean test(T t)

使用示例:
1、消费型接口 Consumer<T>

Consumer<String> service1 = str -> sout str;
service1.accept("Hello!! CSDN");// 打印:Hello!! CSDN

方法:void accept(T t)

2、供给型接口 Supplier<T>

Supplier<Integer> service2 = () -> (int)(Math.random() * 100);// 获取0~100的随机整数
sout service2.get();// 打印:66

方法:T get()

3、函数型接口 Function<T,R>

Function<String, Integer> service3 = str -> str.length();
sout service3.apply("I love China!!");// 打印:14

方法:R apply(T t)

4、断定型接口 Predicate<T>

Integer i1 = 10;
Predicate<Integer> service4 = xx -> i1.equals(xx);
sout service4.test(10);// 打印:true
sout service4.test(20);// 打印:false

方法:boolean test(T t)

3.2 其他函数式接口

(此表格引用自启发博文。)

函数式接口 参数类型 返回值类型 说明
BiFunction<T, U, R> T, U R 对类型为TU的对象应用操作,返回类型为R的对象,包含方法:R apply(T t, U u)
UnaryOperator<T>Function<T>的子接口) T T 对类型为T的参数进行一元运算,并返回类型为T的结果,包含方法:T aaply(T t)
BinaryOperator<T>(BiFunction<T, U, R>的子接口) T, T T 对类型为T的参数进行二元运算,并返回类型为T的结果,包含方法:T apply(T t1, T t2)
BiConsumer<T, U> T, U void 对类型为TU的对象应用操作,包含方法:void accept(T t, U u)
ToIntFunction<T>ToLongFunction<T>ToDoubleFunction<T> T int、long、double 分别计算 int、long、double 的函数
IntFunction<R>LongFunction<R>DoubleFunction<R> int、long、double R 参数分别为 int、long、double 的函数

使用示例:
1、函数型接口 BiFunction<T, U, R>

BiFunction<Character[], Character, Integer> service5 = (charArr, c) -> Arrays.binarySearch(charArr, c);
sout service5.apply(new Character[]{65, 66, 67}, 'B');// 打印:1

方法:R apply(T t, U u)
关于binarySearch(),详情可见Arrays类的第2.2项。

2、函数型接口 UnaryOperator<T>

UnaryOperator<String> service6 = str -> str.trim().split("!")[1].trim().toUpperCase();
sout service6.apply("   Hello KiTi! I am 小白 of csdn   ");// 打印:I AM 小白 OF CSDN

方法:T apply(T t)

3、函数型接口 BinaryOperator<T>

BinaryOperator<List<Character>> service7 = (list1, list2) -> {
    Collections.copy(list2, list1);
    return list2;
};
sout service7.apply(Arrays.asList('C', 'h'), Arrays.asList('#', '#', 'i', 'n', 'a'));// 打印:[C, h, i, n, a]

方法:T apply(T t1, T t2)
关于copy(),详情可见Collections类的第2.10项;关于asList(),详情可见 Arrays 类的第2.1项。

4、消费型接口 BiConsumer<T,R>

BiConsumer<char[], Character>service8 = (charArr, c) -> {
    Arrays.fill(charArr, c);
    sout Arrays.toString(charArr);// 打印:[#, #, #, #, #]
};
service8.accept(new char[]{'进', '步', '*', '于', '辰'}, '#');

方法:void accept(T t, U u)
关于fill(),详情可见 Arrays 类的第2.8项。

5、未知型接口 To[Int/Long?Double]Function<T>

// ToIntFunction<T>
ToIntFunction<List> service9= list -> list.size();
int size = service9.applyAsInt(Arrays.asList(true, 3, 2, 1, "yes", 'f', 'i', 'r', 'e'));// 结果:9

// ToLongFunction<T>
ToLongFunction<Integer> service10 = n-> {
    long startTime = System.nanoTime();
    while ((n--) > 0) {}
    long endTime = System.nanoTime();
    return endTime - startTime;
};
long time = service10.applyAsLong(100000);// 结果:6486400ms

// ToDoubleFunction<T>
ToDoubleFunction<Double> service11 = radian -> Math.toDegrees(radian);
double angle = service11.applyAsDouble(Math.PI);// 结果:180.0

方法:int/long/double applyAs[Int/Long/Double]

6、函数型接口 [Int/Long/Double]Function<R>

// IntFunction<R>
IntFunction<String> service12 = length -> {
    StringBuffer builder = new StringBuffer(10);
    while ((length--) > 0) {
        int x = (int) (Math.random() * 10);// 获取0~9的随机数
        builder.append(x);
    }
    return builder.toString();
};
String code = service12.apply(6);// 结果:695821

// LongFunction<R>
LongFunction<Date> service13 = timeStamp -> new Date(timeStamp);
Date current = service13.apply(System.currentTimeMillis());// 结果:Tue May 09 22:17:26 CST 2023

// DoubleFunction<R>
DoubleFunction<Long> service14 = originN -> Math.round(originN);
long round = service14.apply(10.5);// 结果:11

方法:R apply(int/long/double i)

3.3 其他函数式接口补充

函数式接口 参数类型 返回值类型 说明
断定型接口 `BiPredicate<T, U> T, U boolean 确定类型分别为T/U的对象是否满足某约束,并返回 boolean 值。包含方法:boolean test(T t, U u)

使用示例:
1、断定型接口 `BiPredicate<T,U>:

BiPredicate<String, String > service1 = (t, u) -> t.equals(u);
sout service1.test("abc", "abc");// 打印:true
sout service1.test("abc", "123");// 打印:false

方法:boolean test(T t, U u)

3.4 示例补充说明

大家在看上面的示例时,肯定想吐槽:“你写的那些方法体,很多都是多此一举。”
以实用性的角度来说的确是,例如:sout strstr.lengthxx > 0? true: false,直接调用相应方法不香么?还用 Lambda 转个弯实现。

那我为何还这样写? \color{grey}{那我为何还这样写?} 那我为何还这样写?
因为我觉得使用 Lambda 的核心思维在于 灵活、扩展、通用 \color{red}{灵活、扩展、通用} 灵活、扩展、通用。因此,我写那些示例的初衷是 “任意举例、简单易懂” \color{green}{“任意举例、简单易懂”} 任意举例、简单易懂,目的不在于实现何种功能,而是阐述 Lambda 的使用。

4、Lambda表达式的三种引用

先言: \color{red}{先言:} 先言:
以下对于引用的示例,我会尽量用上文中Java内置函数式接口及其所举示例进行 “演变” “演变” 演变举例,从而降低大家阅读代码的成本。

4.1 方法引用

4.1.1 概述

先说结论: \color{red}{先说结论:} 先说结论:

方法引用中所使用的 “缺省参数列表” \color{red}{“缺省参数列表”} 缺省参数列表必须与抽象方法的参数列表相同,返回值类型也必须相同。

何为“缺省参数列表”? \color{grey}{何为“缺省参数列表”?} 何为缺省参数列表

“缺省参数列表”指方法引用中已指定参数与所引用方法的参数列表相比较的缺失参数部分。

这是我自定义的概念,看着有点绕口,我会在示例中举例说明。

方法引用格式: \color{green}{方法引用格式:} 方法引用格式:

  1. 对象 :: 成员方法名
  2. 类 :: 类方法名
  3. 类 :: 成员方法名

4.1.2 说明示例

4.1.2.1 boolean equals(String str)

为 String 类的成员方法boolean equals(String str)定义方法引用。
以此例为基础进行举例。

BiPredicate<String, String > service1 = (t, u) -> t.equals(u);

演变办法一:

// 格式:类 :: 成员方法名
BiPredicate<String, String> service = String::equals;
sout service.test("csdn", "bilibili");// 打印:false
sout service.test("csdn", "csdn");// 打印:true

为什么选择 B i P r e d i c a t e 接口实现方法引用? \color{red}{为什么选择 BiPredicate 接口实现方法引用?} 为什么选择BiPredicate接口实现方法引用?

  1. equals()的返回值类型为 boolean,则此抽象方法的返回值类型也必须是 boolean;
  2. equals()是成员方法,一共需要2个变量,方法引用为String::equals,由于未指定任何变量,故缺省2个变量。而这两个变量必须由抽象方法的参数列表提供,故参数列表必须且仅有两个参数,且类型要与方法引用的类型相同;
  3. equals()所需的两个变量,类型都是 String,则抽象方法的两个参数的类型只能是 String。故<T><U> 类型实参 \color{green}{类型实参} 类型实参为 String。

演变办法二:

// 格式:对象 :: 成员方法名
String str = "csdn";
Predicate<String> service = str::equals;
sout service.test("bilibili");// 打印:false
sout service.test("csdn");// 打印:true

为什么选择 P r e d i c a t e 接口实现方法引用? \color{red}{为什么选择 Predicate接口实现方法引用?} 为什么选择Predicate接口实现方法引用?

  1. equals()的返回值类型为 boolean,则此抽象方法的返回值类型也必须是 boolean;
  2. equals()是成员方法,一共需要2个变量,方法引用为str::equals,由于已指定一个变量,故缺省1个变量。而这两个变量必须由抽象方法的参数列表提供,故参数列表必须且仅有一个参数,且类型要与方法引用的类型相同;
  3. equals()所需的两个变量,类型都是 String,则抽象方法的参数的类型只能是 String。故<T> 类型实参 \color{green}{类型实参} 类型实参为 String。
4.1.2.2 void fill()

为 Arrays 类的静态方法void fill()定义方法引用。
以此例为基础进行举例。

BiConsumer<char[], Character>service8 = (charArr, c) -> {
    Arrays.fill(charArr, c);
    sout Arrays.toString(charArr);// 打印:[#, #, #, #, #]
};
service8.accept(new char[]{'进', '步', '*', '于', '辰'}, '#');

演变:

// 格式:类 :: 静态方法名
BiConsumer<char[], Character> service8 = Arrays::fill;
char[] charArr = new char[]{'进', '步', '*', '于', '辰'};
service8.accept(charArr, '#');
sout Arrays.toString(charArr);// 打印:[#, #, #, #, #]

为什么选择 B i C o n s u m e r 接口实现方法引用? \color{red}{为什么选择 BiConsumer接口实现方法引用?} 为什么选择BiConsumer接口实现方法引用?

  1. fill()无返回值,accept()也无返回值,故匹配;
  2. fill()是类方法,需要两个变量,方法引用是Arrays::fill,由于未指定任何变量,故缺省2个变量。而这两个变量必须由抽象方法的参数列表提供,故参数列表必须且仅有两个参数,且类型要与方法引用的类型相同;
  3. fill()的第1个参数类型为基本数据类型数组,为char[];第2个参数类型为基本数据类型,为char。这2个参数都由accept()提供,故<T> 类型实参 \color{green}{类型实参} 类型实参char[]<R> 类型实参 \color{blue}{类型实参} 类型实参为 Character,

留言: \color{purple}{留言:} 留言:
泛型的类型实参只能是,为何这里可以是char[](数组),欢迎各位博友在评论区讨论!!

4.2 构造器引用

4.2.1 概述

格式: \color{green}{格式:} 格式:类 :: new

说明: \color{purple}{说明:} 说明:
顾名思义,“构造器引用”的作用就是实例化,即返回实例
例如:为实体类Users创建构造器引用,则构造器引用固定Users :: new,即返回一个 Users 实例。

约束: \color{brown}{约束:} 约束:
抽象方法的参数列表决定了匹配哪个构造方法,即构造器引用等同于构造方法

4.2.2 示例

实体类。

class Users {
    private Integer id;
    private String[] hobby;

    public Users() {
    }

    public Users(Integer id) {
        this.id = id;
    }

    public Users(String[] hobby) {
        this.hobby = hobby;
    }

    public Users(Integer id, String[] hobby) {
        this.id = id;
        this.hobby = hobby;
    }
    
    @Override
    public String toString() {
        return "Users{" +
                "id=" + id +
                ", hobby=" + Arrays.toString(hobby) +
                '}';
    }
}

测试。

Supplier<Users> service1 = Users::new;
Users user1 = service1.get();
sout user1;// 打印:Users{id=null, hobby=null}

Function<Integer, Users> service2 = Users::new;
Users user2 = service2.apply(1001);
sout user2;// 打印:Users{id=1001, hobby=null}

Function<String[], Users> service3 = Users::new;
Users user3 = service3.apply(new String[]{"编程", "Game"});
sout user3;// 打印:Users{id=null, hobby=[编程, Game]}

BiFunction<Integer, String[], Users> service4 = Users::new;
Users user4 = service4.apply(1002, new String[]{"java", "cf"});
sout user4;// 打印:Users{id=1002, hobby=[java, cf]}

4.3 数组引用

格式: \color{orange}{格式:} 格式:类型[] :: new

说明: \color{dark}{说明:} 说明:
与构造器引用同理。不过,数组引用返回的是数组。(我暂不知如何使用数组引用创建非空数组)

示例:

Function<Integer, Integer[]> service1 = Integer[]::new;
Integer[] arr = service1.apply(5);
sout Arrays.toString(arr);// 打印:[null, null, null, null]

5、Lambda表达式的作用域

以下阐述转载自博文《Lambda表达式超详细总结》。

Lambda表达式可以看作是匿名内部类实例化的对象,Lambda表达式对变量的访问限制和匿名内部类一样。因此Lambda表达式可以访问局部变量、局部引用,静态变量和成员变量。

5.1 引用局部常量

规定在Lambda表达式中只能引用由final修饰的局部变量,即局部常量,包括局部基本类型常量和局部引用类型常量。

5.1.1 引用局部基本类型常量

double d1 = 10.2;-------------------------------------------A
// final double d1 = 10.2;----------------------------------------B
UnaryOperator<Double> service = d -> Math.floor(d + d1);----C
// d1 = 5.1;------------------------------------------------D
sout service.apply(5.9);// 打印:16.0

d1定义为变量(A),可当引用于 Lambda 中时(C),会隐式转为常量,但当为d1赋值时(D),这种“隐式转换”功能会失效,d1仍为变量,则C会编译报错。
若将d1显式定义为常量(B),则C可编译通过,但由于常量不可修改,D将会编译报错。

5.1.2 引用局部引用类型常量

示例1:

String subStr = "csdn";
Predicate<String> service = str -> str.contains(subStr);
sout service.test("csdn, bilibili, 博客园");// 打印:true
// subStr = "bili";

此示例与上文中【引用局部基本类型常量】的示例同理。

示例2:

List list = new ArrayList();
list.add(2023);
list.add("年");
list.add(5.12);
Supplier<Integer> service = () -> list.size();
sout service.get();// 打印:3
list.add(true);
sout service.get();// 打印:4

执行list.add(true)是对list进行了修改,按照上面的结论,这个示例是编译报错的。可实际上编译通过。为什么?难道上面的结论有纰漏??
在后面加上这么一条代码试试:

list = new ArrayList();

这样就编译报错了。大家看出来了吧。。。

结论: \color{red}{结论:} 结论:
由 Lambda 引用的局部常量不可修改,指的是不可修改引用指向

5.2 引用成员变量、类变量

public class TestReference {
	String originStr1 = "csdn,bilibili,博客园";
	static String originStr2 = "csdn,bilibili,博客园";
	
	public static void main(String[] args) {
	    Supplier<TestReference> service1 = TestReference::new;
	    TestReference t1 = service1.get();
	
	    Supplier<String[]> service2 = () -> t1.originStr1.split(",");
	    String[] arr1 = service2.get();-----------A
	    sout Arrays.toString(arr1);// 打印:[csdn, bilibili, 博客园]
	    t1.originStr1 = "";-----------------------B
	
	    Supplier<String[]> service3 = () -> originStr2.split(",");
	    String[] arr2 = service3.get();-----------C
		sout Arrays.toString(arr2);// 打印:[csdn, bilibili, 博客园]
	    originStr2 = "";--------------------------D
	}
}

B、D处分别修改成员变量originStr1与类变量originStr2,都编译通过。可见,Lambda 不限制对成员变量和类变量的引用

留言: \color{brown}{留言:} 留言:
至于 Lambda 有没有如上文中【局部常量】般将成员变量或类变量隐式转为常量,暂未可知。不过,我觉得没有隐式转换,因为B、D处编译通过。

5.3 引用成员常量、类常量

以上述【引用成员变量、类变量】的示例为基础,在成员变量originStr1和类变量originStr2的定义前加上final,即:

final String originStr1 = "csdn,bilibili,博客园";
final static String originStr2 = "csdn,bilibili,博客园";

则A、C处都编译通过,说明,Lambda 不限制对成员常量和类常量的引用;而B、D处都编译报错。这是常量本身的性质,与 Lambda 无关。

5.4 限制访问局部变量的原因

具体原因,那位前辈已经总结得很全面,我就不班门弄斧了,详述请查阅博文《Lambda表达式超详细总结》(转发)的第8.3项。

6、最后

本文中的示例是为了方便大家理解、以及阐述 Lambda 表达式的运用而简单举出的,不一定有实用性。示例很多,不过,我所举的示例都是 “以简为宗旨” \color{green}{“以简为宗旨”} 以简为宗旨,重心不在于使用 Lambda 表达式编写多么强大的功能,而在于尽量扩展对 Lambda 表达式的使用,让大家能够更透彻地理解它的格式、规范、限制等。

P S : \color{blue}{PS:} PS
这是我迄今为止写过的内容最多的一篇文章,超1.5万字,我都有点佩服我自己。

当然,这个内容量与大神们动则几万、十几万的大作相比,不值一提(我不是谦虚,类如几万、十几万的大作,那完全是上了另一个层面的文章了,用“论文”形容更贴切)。不过,我还是挺有成就感的且受益匪浅!

本文完结。文章来源地址https://www.toymoban.com/news/detail-448849.html

到了这里,关于关于对【java中的Lambda表达式】的理解与简述的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 深入理解lambda表达式

    var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.Use(async (context, next) = { // Add code before request. }); 这段C#代码是用于设置ASP.NET Core应用中的中间件。下面是详细解释: app.Use : 这个方法是用来向应用的请求处理管道中添加一个中间件的。在ASP.NET Core中,中间件用于处

    2024年02月20日
    浏览(48)
  • JAVA8-lambda表达式8:在设计模式-模板方法中的应用

    JAVA8-lambda表达式1:什么是lambda表达式 JAVA8-lambda表达式2:常用的集合类api JAVA8-lambda表达式3:并行流,提升效率的利器? JAVA8-lambda表达式4:Optional用法 java8-lambda表达式5:toMap引发的线上故障 JAVA8-lambda表达式6:重构和定制收集器 JAVA8-lambda表达式7:重要的函数接口 最近在公司

    2024年02月14日
    浏览(52)
  • QT中的lambda表达式

    面是对Qt中在QObject::connect()中的lambda表达式常用用法 QString str(\\\"I am a string!\\\"); device=str; connect(ui- PushButton::clicked,[](bool){qDebug()\\\"device==\\\"device;}); 表达式详解 a1 第一个参数含义 第一个参数ui-pushButton:表示对象; a2 第二个参数含义 第二个参数QPushButton::clicked:表示对象包含的信号(

    2024年02月04日
    浏览(43)
  • C++ 中的Lambda表达式

    Lambda 表达式 (lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是 一个匿名函数,即没有函数名的函数 。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。 闭包 就是能够读取其他函数内部变量

    2024年02月09日
    浏览(51)
  • 探索Python中的函数式编程:Lambda表达式与函数式工具【第135篇—Lambda表达式】

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 在Python编程世界中,函数式编程逐渐成为了一种流行的范式,特别是在处理数据和编写简洁、高效代码时。函数式编程的核心思想是将计算视

    2024年04月08日
    浏览(87)
  • 进阶JAVA篇- Lambda 表达式与 Lambda 表达式的省略规则

    目录         1.0 什么是 Lambda 表达式?         1.1 既然跟匿名内部类相关,先来回顾匿名内部类。          1.2 Lambda 表达式与匿名内部类之间的关系。         1.3 函数式接口         1.4 在具体代码中来操作一下         2.0 Lambda 表达式省略规则          Lambda 表达

    2024年02月08日
    浏览(55)
  • Java- Lambda表达式

    目录 一、Lambda简介 二、Lambda使用前提 三、Lambda语法 1.操作符 a.\\\"-\\\"  b.\\\"::\\\" 2.格式  a.无参数 b.有参数 四、Lambda演化过程 五、Lambda实现排序 Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)

    2024年02月03日
    浏览(76)
  • Lambda表达式(JAVA)

    注:如果没有学过 匿名内部类 和 接口 不推荐往下看。 (parameters) - expression 或 (parameters) -{ statements; } parameters:表示参数列表; -:可理解为“被用于”的意思; expression:表示一条语句; statements:表示多条语句。 Lambda可以理解为:Lambda就是匿名内部类的简化。 lambda表达式

    2024年02月08日
    浏览(54)
  • Java Lambda表达式

    1.1 函数式编程思想概括 在数学中,函数就是有输入量、输出量的一套计算方案,也就是“拿数据做操作” 面向对象思想强调“必须通过对象的形式来做事情” 函数式思想则尽量忽略面

    2024年02月07日
    浏览(61)
  • Java Lambda 表达式

    💗wei_shuo的个人主页 💫wei_shuo的学习社区 🌐Hello World ! Java Lambda 表达式是 Java 8 引入的一种函数式编程特性,它是一种轻量级的匿名函数,允许我们将函数作为方法的参数进行传递。Lambda 表达式可以理解为是一种简洁的方式来表示可传递的代码块,它可以替代传统的匿名内

    2024年02月08日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包