公司网站不备案,WordPress内容页面加边框,wordpress升级php版本崩溃,wordpress视频列表一、介绍
1、简介
Java的Lambda表达式是Java 8引入的一个特性#xff0c;它支持函数式编程#xff0c;允许将函数作为方法的参数或返回值#xff0c;从而简化了匿名内部类的使用#xff0c;并提供了对并行编程的更好支持。
可以将Lambda表达式理解为一个匿名函数它支持函数式编程允许将函数作为方法的参数或返回值从而简化了匿名内部类的使用并提供了对并行编程的更好支持。
可以将Lambda表达式理解为一个匿名函数 Lambda表达式允许将一个函数作为另外一个函数的参数 我们可以把 Lambda 表达式理解为是一段可以传递的代码将代码作为实参,也可以理解为函数式编程将一个函数作为参数进行传递。
2、优点
Lambda表达式的主要优势包括
简化匿名内部类的使用使代码更加简洁明了。支持函数式编程允许函数作为第一类对象进行传递和操作。促进并行编程因为函数式编程中的纯函数天然具备无副作用的特性使得在并行编程中更容易实现可靠的多线程和并行处理。
3、用途
Lambda表达式主要用于函数式接口即只包含一个抽象方法的接口可以使用FunctionalInterface注解进行标识。常用场景有
创建Runnable实例Runnable runnable () - {System.out.println(Hello, Lambda!);};实现Consumer接口numbers.forEach(n - System.out.println(n));实现Predicate接口filteredNames names.stream().filter(name - name.length() 5).collect(Collectors.toList());创建线程new Thread(() - System.out.println(haha)).start();
二、语法与使用
1、基本语法
([Lambda参数列表即形参列表]) - {Lambda体即方法体} 如果主体只有一行代码可以更简化去掉{}
(parameters) - expression1Lambda 表达式关注的是接口中方法的返回值和参数方法名不重要 2使用 -将参数和实现逻辑分离 ( ) 中的部分是需要传入Lambda体中的参数参数可以是任意合法的Java参数列表可以为空或包含一个或多个参数 { } 中部分接收来自 ( ) 中的参数完成一定的功能。Lambda主体可以是一个表达式也可以是一个代码块。如果主体是一个表达式它将直接返回该表达式的结果。如果主体是一个代码块它将按照常规的Java语法执行并且您可能需要使用return语句来返回值。 3只有函数式接口的变量或者是函数式接口才能够赋值为Lambda表达式。这个接口中可以有默认方法或者是静态方法。
2、使用条件
lambda表达式和方法引用使用前提函数式接口 1FunctionalInterface 语法格式严格要求当前接口有且只能有一个尚未完成的缺省属性为 public abstract 修饰方法。Lambda表达式的使用前提是存在一个接口该接口中有且只有一个抽象方法。在主方法中可以通过创建接口的匿名内部类或使用Lambda表达式来调用该接口的方法。 2函数式接口一般用于方法的增强直接作为方法的参数实现函数式编程。只有函数式接口的变量或者是函数式接口才能够赋值为Lambda表达式。这个接口中可以有默认方法或者是静态方法。
3、四种lambda表达式
1无参数无返回值
() - System.out.println(Hello, Lambda!);如
//接口设计
FunctionalInterface
interface A {void 方法名真的没有用();
}
//方法设计
public static void testLambda(A a) {a.方法名真的没有用();
}
//代码实现
public static void main(String[] args) {//1.匿名内部类方法//接口无法实例化这里实例化的是 A 接口的实现类对象(该方法在jdk1.8以后被lambda表达式完虐)testLambda(new A() {//缺省属性为abstract需要重写Overridepublic void 方法名真的没有用() {System.out.println(无参数返回值 匿名内部类对象方法实现);}});/*2. Lambda 表达式实现【分析】void 方法名真的没有用();接口方法【返回值类型】 void无返回值接口方法【参数】 无参数*/testLambda(() - {System.out.println(Lambda 表达式初体验);});//Lambda 表达式有且只有一行代码可以省略大括号testLambda(() - System.out.println(Lambda 表达式初体验));2 无参数有返回值
(x, y) - System.out.println(x y);(x, y) - {int sum x y;System.out.println(Sum: sum);return sum;
}//接口设计
FunctionalInterface
interface SupplierT {/*** 无参数有返回值方法泛型约束的是接口对应的返回值数据类型要求按照泛型约束返回对应的数据内容** return 返回一个数据符合泛型约束*/T get();
}
/** 当前方法要求返回一个字符串数据内容*/
public static String testLambda(SupplierString s) {return s.get();
}
public static void main(String[] args) {/*【分析】T get(); 泛型约束为 String String get();接口方法【返回值类型】 String接口方法【参数】 无参数Lambda 格式() - {必须返回一个 String 类型}*/String s1 testLambda(() - {return 这里也是一个字符串;});System.out.println(s1);/*Lambda 优化只要 - 之后是一个 字符串数据内容就可以满足当前 Lambda 所需可以省略 return 前提是当前 Lambda 有且只有一行代码*/String s2 testLambda(() - 这里也是一个字符串);System.out.println(s2);/*Lambda 内部使用使用方法局部变量*/String str name王小明age23country中国;String s3 testLambda(() - {// str 是当前 main 方法局部变量Lambda 内部可以直接使用String[] split str.split();return split[0];});System.out.println(s3);//返回王小明
}3 有参数无返回值
FunctionalInterface
interface ConsumerT {/*** 消费者接口数据最终处理接口数据处理终止方法接口对应的方法要求方法有参数无返回值** param t 泛型数据数据类型 T 支持任意类型在接口约束之后要求符合数据类型一致化要求*/void accept(T t);
}
/*** 有参数无返回 Lambda 测试方法方法参数是 String 类型和针对于 String 类型* 进行数据处理的 Consumer 接口Consumer 接口可以传入实现类对象和 Lambda 表达式** param str 目标处理的 String 字符串数据* param handle 已经约束为处理 String 类型数据的 Consumer 接口处理器*/
public static void testLambda(String str, ConsumerString handle) {handle.accept(str);
}
public static void main(String[] args) {/*1、匿名内部类 Low*/testLambda(孟州市炒面第一名, new ConsumerString() {Overridepublic void accept(String t) {System.out.println(t);}});/*2. Lambda 表达式【分析】void accept(T t); 泛型约束为 String void accept(String t);接口方法【返回值】 void接口方法【参数】 1 个参数String 类型Lambda 格式Lambda 小括号中的临时变量名称没有数据类型体现需要【联想】目标方法数据类型只按照参数的个数定义临时小变量(s) - {大括号中无需返回值类型}Lambda 表达式临时变量 s 对应的数据类型为 String 类型 【联想可得】*/testLambda(lambda表达式需要联想, (s) - {System.out.println(Arrays.toString(s.toCharArray()));});/*Lambda 优化1. 代码块有且只有一行可以省略大括号2. 小括号中有且只有一个 参数可以省略小括号【注意】Lambda 承担的角色是一个针对于 String 字符串的处理器*/testLambda(lambda表达式需要联想, s - System.out.println(Arrays.toString(s.toCharArray())));
}4有参数有返回值
4、方法引用拓展
当Lambda表达式满足某种条件的时候使用方法引用可以再次简化代码。
1构造引用
当Lambda表达式是通过new一个对象来完成的那么可以使用构造引用。
import java.util.function.Supplier;
public class TestLambda {public static void main(String[] args) {
// SupplierStudent s () - new Student();SupplierStudent s Student::new;}//实际过程将new Student()赋值给了Supplier这个函数式接口中的那个抽象方法
}2 类名::实例方法
Lambda表达式的的Lambda体也是通过一个对象的方法完成但是调用方法的对象是Lambda表达式的参数列表中的一个剩下的参数正好是给这个方法的实参。
import java.util.TreeSet;
public class TestLambda {public static void main(String[] args) {TreeSetString set new TreeSet((s1,s2) - s1.compareTo(s2));
}3 对象::实例方法
*/ //类名::实例方法TreeSetString set new TreeSet(String::compareTo);set.add(Hello);set.add(isea_you);// set.forEach(t - System.out.println(t));//Hello \n isea_youset.forEach(System.out::println);//1对象::实例方法,Lambda表达式的(形参列表)与实例方法的(实参列表)类型个数是对应}
}4类名::静态方法
package com.isea.java;
import java.util.stream.Stream;
public class TestLambda {public static void main(String[] args) {
// StreamDouble stream Stream.generate(() - Math.random());
// 类名::静态方法, Lambda表达式的(形参列表)与实例方法的(实参列表)类型个数是对应StreamDouble stream Stream.generate(Math::random);stream.forEach(System.out::println);}
}5、变量捕获
5.1、匿名内部类的变量捕获
在Java中匿名内部类可以捕获外部变量即在匿名内部类中引用并访问外部作用域的变量。这种行为称为变量捕获Variable Capturing。在匿名内部类中可以捕获以下类型的变量
1实例变量Instance Variables如果匿名内部类位于一个实例方法中它可以捕获并访问该实例的实例变量。
2静态变量Static Variables匿名内部类可以捕获并访问包含它的类的静态变量。
3方法参数Method Parameters匿名内部类可以捕获并访问包含它的方法的参数。
4本地变量Local Variables匿名内部类可以捕获并访问声明为final的本地变量。从Java 8开始final关键字可以省略但该变量实际上必须是最终的即不可修改。
当匿名内部类捕获变量时它们实际上是在生成的字节码中创建了一个对该变量的副本。这意味着即使在外部作用域中的变量发生改变匿名内部类中捕获的变量仍然保持其最初的值。demo
public class OuterClass {private int instanceVariable 10;private static int staticVariable 20;public void method() {final int localVar 30; // 或者直接使用 Java 8 的隐式 finalRunnable runnable new Runnable() {Overridepublic void run() {System.out.println(Instance variable: instanceVariable);System.out.println(Static variable: staticVariable);System.out.println(Local variable: localVar);}};runnable.run();}
}5.2、Lambda表达式的变量捕获
在Lambda表达式中同样可以捕获外部作用域的变量。Lambda表达式可以捕获以下类型的变量
1实例变量Instance VariablesLambda表达式可以捕获并访问包含它的实例的实例变量。
2静态变量Static VariablesLambda表达式可以捕获并访问包含它的类的静态变量。
3方法参数Method ParametersLambda表达式可以捕获并访问包含它的方法的参数。
4本地变量Local VariablesLambda表达式可以捕获并访问声明为final的本地变量。从Java 8开始final关键字可以省略但该变量实际上必须是最终的即不可修改。
与匿名内部类不同Lambda表达式不会创建对变量的副本而是直接访问变量本身。这意味着在Lambda表达式中捕获的变量在外部作用域中发生的改变也会在Lambda表达式中反映出来。demo:
public class LambdaVariableCapture {private int instanceVariable 10;private static int staticVariable 20;public void method() {int localVar 30;// Lambda表达式捕获外部变量Runnable runnable () - {System.out.println(Instance variable: instanceVariable);System.out.println(Static variable: staticVariable);System.out.println(Local variable: localVar);};runnable.run();}
}三、使用场景
1、在集合中的使用
Lambda表达式在Collection接口中的使用主要涉及对集合进行迭代、筛选和转换等操作。在Java 8及以上的版本中Collection接口增加了一些默认方法例如forEach()、removeIf()和stream()等使得使用Lambda表达式更加方便。
1.1、Collection接口
1迭代 ListString stringList Arrays.asList(apppe,organge,banana);// 原来的方式for (String s : stringList) {System.out.println(s);}// lambda 表达式stringList.forEach(s-{System.out.println(s);});
2筛选
ListInteger numbers Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);numbers.removeIf(n - n % 2 0);3转换
ListString names Arrays.asList(Alice, Bob, Charlie);ListInteger nameLengths names.stream().map(name - name.length()).collect(Collectors.toList());4获取集合流
ListInteger numbers Arrays.asList(1, 2, 3, 4, 5);StreamInteger stream numbers.stream();5使用filter()筛选集合元素
ListString names Arrays.asList(Alice, Bob, Charlie);ListString filteredNames names.stream().filter(name - name.startsWith(A)).collect(Collectors.toList());1.2、 List接口
1遍历
ListString fruits Arrays.asList(Apple, Banana, Orange);fruits.forEach(fruit - System.out.println(fruit));2过滤
ListInteger numbers Arrays.asList(1, 2, 3, 4, 5);ListInteger evenNumbers numbers.stream().filter(number - number % 2 0).collect(Collectors.toList());3映射
ListString names Arrays.asList(Alice, Bob, Charlie);ListInteger nameLengths names.stream().map(name - name.length()).collect(Collectors.toList());4查找
ListString fruits Arrays.asList(Apple, Banana, Orange);OptionalString foundFruit fruits.stream().filter(fruit - fruit.startsWith(B)).findFirst();5排序
ListInteger numbers Arrays.asList(5, 2, 8, 1, 6, 3, 9, 4, 7, 10);ListInteger sortedNumbers numbers.stream().sorted().collect(Collectors.toList());1.3、Map接口
1迭代Map的键值对
MapString, Integer map new HashMap();
map.put(Alice, 25);
map.put(Bob, 30);
map.put(Charlie, 35);map.forEach((key, value) - System.out.println(key : value));2遍历Map的键或值
MapString, Integer map new HashMap();
map.put(Alice, 25);
map.put(Bob, 30);
map.put(Charlie, 35);map.keySet().forEach(key - System.out.println(key));
map.values().forEach(value - System.out.println(value));3使用Stream过滤Map的键值对
MapString, Integer map new HashMap();
map.put(Alice, 25);
map.put(Bob, 30);
map.put(Charlie, 35);MapString, Integer filteredMap map.entrySet().stream().filter(entry - entry.getValue() 30).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));4对Map的值进行映射
MapString, Integer map new HashMap();
map.put(Alice, 25);
map.put(Bob, 30);
map.put(Charlie, 35);MapString, String mappedMap map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry - Age: entry.getValue()));5对Map的键或值进行归约操作
MapString, Integer map new HashMap();
map.put(Alice, 25);
map.put(Bob, 30);
map.put(Charlie, 35);int sumOfValues map.values().stream().reduce(0, (a, b) - a b);
String concatenatedKeys map.keySet().stream().reduce(, (a, b) - a b);