唠叨的豌豆 · 在JAVA中如何将一个Object转换成Ar ...· 2 天前 · |
怕老婆的钱包 · 解析csv文件,读取百万级数据_51CTO博 ...· 昨天 · |
紧张的香瓜 · c++ string utf16 - CSDN文库· 23 小时前 · |
强健的碗 · basic_string 类 | ...· 23 小时前 · |
一身肌肉的板栗 · C++类结构体与json相互转换 - ...· 23 小时前 · |
瘦瘦的棒棒糖 · 关于执行策略 - PowerShell | ...· 3 月前 · |
冷静的酱牛肉 · ChatGPT教你如何用Python和Mat ...· 1 年前 · |
沉着的水龙头 · Jupyter。在spyder/jupyte ...· 1 年前 · |
失落的饭卡 · python pandas: ...· 1 年前 · |
Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。
Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
使用 Lambda 表达式可以使代码变的更加简洁紧凑。
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)
在 Java8Tester.java 文件输入以下代码:
执行以上脚本,输出结果为:
$ javac Java8Tester.java $ java Java8Tester 10 + 5 = 15 10 - 5 = 5 10 x 5 = 50 10 / 5 = 2 Hello Runoob Hello Google 使用 Lambda 表达式需要注意以下两点:
Lambda 表达式主要用来定义行内执行的方法类型接口(例如,一个简单方法接口)。在上面例子中,我们使用各种类型的 Lambda 表达式来定义 MathOperation 接口的方法,然后我们定义了 operation 的执行。
Lambda 表达式免去了使用匿名方法的麻烦,并且给予 Java 简单但是强大的函数化的编程能力。
在 Java8Tester.java 文件输入以下代码:
执行以上脚本,输出结果为:
$ javac Java8Tester.java $ java Java8Tester Hello! Runoob我们也可以直接在 lambda 表达式中访问外层的局部变量:
lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)
int num = 1; Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num)); s.convert(2); num = 5; //报错信息:Local variable num defined in an enclosing scope must be final or effectively final
在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。
String first = ""; Comparator<String> comparator = (first, second) -> Integer.compare(first.length(), second.length()); //编译会出错
彬
117***8834@qq.com
System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
这里还有另外一种写法
System.out.println("10+5=" + addition.operation(10, 5));
interface MathOperation { int operation(int a, int b); }
此接口要求必须是函数式接口,如果其中有两个方法则lambda表达式会编译错误。但java8的新特性如许实现如下写法:
interface MathOperation { int operation(int a, int b); default int addition(int a, int b){ return a+b; }
下面是使用 lambdas 来实现 Runnable 接口的示例:
// 1.1使用匿名内部类 new Thread(new Runnable() { @Override public void run() { System.out.println("Hello world !"); }).start(); // 1.2使用 lambda expression new Thread(() -> System.out.println("Hello world !")).start(); // 2.1使用匿名内部类 Runnable race1 = new Runnable() { @Override public void run() { System.out.println("Hello world !"); // 2.2使用 lambda expression Runnable race2 = () -> System.out.println("Hello world !"); // 直接调用 run 方法(没开新线程哦!) race1.run(); race2.run();
Runnable 的 lambda 表达式,使用块格式,将五行代码转换成单行语句。 接下来,在下一节中我们将使用 lambdas 对集合进行排序。
使用 Lambdas 排序集合
在 Java 中,Comparator 类被用来排序集合。 在下面的例子中,我们将根据球员的 name 、
surname 、 name 长度 以及 最后一个字母 。 和前面的示例一样,先使用匿名内部类来排序,然后再使用 lambda 表达式精简我们的代码。
在第一个例子中,我们将根据name来排序list。 使用旧的方式,代码如下所示:
String[] players = {"Rafael Nadal", "Novak Djokovic", "Stanislas Wawrinka", "David Ferrer", "Roger Federer", "Andy Murray", "Tomas Berdych", "Juan Martin Del Potro", "Richard Gasquet", "John Isner"}; // 1.1 使用匿名内部类根据 name 排序 players Arrays.sort(players, new Comparator<String>() { @Override public int compare(String s1, String s2) { return (s1.compareTo(s2));使用 lambdas,可以通过下面的代码实现同样的功能:
// 1.2 使用 lambda expression 排序 players Comparator<String> sortByName = (String s1, String s2) -> (s1.compareTo(s2)); Arrays.sort(players, sortByName); // 1.3 也可以采用如下形式: Arrays.sort(players, (String s1, String s2) -> (s1.compareTo(s2))); 其他的排序如下所示。 和上面的示例一样,代码分别通过匿名内部类和一些lambda表达式来实现Comparator : // 1.1 使用匿名内部类根据 surname 排序 players Arrays.sort(players, new Comparator<String>() { @Override public int compare(String s1, String s2) { return (s1.substring(s1.indexOf(" ")).compareTo(s2.substring(s2.indexOf(" ")))); // 1.2 使用 lambda expression 排序,根据 surname Comparator<String> sortBySurname = (String s1, String s2) -> ( s1.substring(s1.indexOf(" ")).compareTo( s2.substring(s2.indexOf(" ")) ) ); Arrays.sort(players, sortBySurname); // 1.3 或者这样,怀疑原作者是不是想错了,括号好多... Arrays.sort(players, (String s1, String s2) -> ( s1.substring(s1.indexOf(" ")).compareTo( s2.substring(s2.indexOf(" ")) ) ) // 2.1 使用匿名内部类根据 name lenght 排序 players Arrays.sort(players, new Comparator<String>() { @Override public int compare(String s1, String s2) { return (s1.length() - s2.length()); // 2.2 使用 lambda expression 排序,根据 name lenght Comparator<String> sortByNameLenght = (String s1, String s2) -> (s1.length() - s2.length()); Arrays.sort(players, sortByNameLenght); // 2.3 or this Arrays.sort(players, (String s1, String s2) -> (s1.length() - s2.length())); // 3.1 使用匿名内部类排序 players, 根据最后一个字母 Arrays.sort(players, new Comparator<String>() { @Override public int compare(String s1, String s2) { return (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1)); // 3.2 使用 lambda expression 排序,根据最后一个字母 Comparator<String> sortByLastLetter = (String s1, String s2) -> (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1)); Arrays.sort(players, sortByLastLetter); // 3.3 or this Arrays.sort(players, (String s1, String s2) -> (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1)));
天命风流
lic***geek@163.com
奋斗的小猿
157***09440@163.com
以下实例反映出 lambda 不一定需要 final 关键字才可以访问外部变量。
public class LambdaTest { final static String hello = "Hello, "; private static String goodbye = "Goodbye, "; public static void main(String[] args) { GreetingMessage message1 = (String message) -> System.out.println(hello + message); GreetingMessage message2 = (message) -> //goodbye = "the time is late, I'd go now, goodbye"; goodbye += "the time is late, I'd go now, "; System.out.println(goodbye + message); message1.sayMessage("张三"); message2.sayMessage("李四"); interface GreetingMessage { void sayMessage(String message);运行程序后,结果 :
Hello, 张三 Goodbye, the time is late, I'd go now, 李四
ByVie
635***000@qq.com
public class Demo01Inner { public static void main(String[] args) { //使用匿名内部类的方式实现多线程。 new Thread(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + "执行了"); }).start(); //使用Lambda表达式实现多线程 new Thread(() -> System.out.println(Thread.currentThread().getName() + "执行了")).start();匿名内部类可以省去单独创建 .java 文件的操作。但是匿名内部类也是有缺点的,写法太冗余了,里面有很多多余的部分。
匿名内部类也有简化写法,匿名内部类的简化写法是 Lambda 表达式匿名内部类中最关键的内容是方法的参数,方法体,以及返回值,而在 Lambda 表达式中,关注的就是这三个关键的东西。
Lambda 表达式的标准格式:
(参数类型 参数名) -> { return 返回值;格式解释:
- 小括号中的参数和之前方法的参数写法一样,可以写任意个参数,如果多个参数,要使用逗号隔开。
-> 是一个运算符,表示指向性动作。 大括号中的方法体以及 return 返回值的写法和之前方法的大括号中的写法一样。Lambda 表达式是函数式编程思想。
函数式编程:可推导,就是可省略。
因为在 Thread 构造方法中需要 Runnable 类型的参数,所以可以省略 new Runnable。- 因为 Runnable 中的只有一个抽象方法 run,所以重写的必然是这个 run 方法,所以可以省略 run 方法的声明部分(public void run)
Lambda 表达式可以省略面向对象中的一些条条框框,让我们只关注最核心的内容。
public class Demo02Lambda { public static void main(String[] args) { //实现多线程(单独创建.java) new Thread(new Task()).start(); //使用匿名内部类的方式实现多线程 new Thread(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + "执行了"); }).start(); //使用Lambda表达式完成多线程 new Thread(() -> { System.out.println(Thread.currentThread().getName() + "执行了"); }).start();匿名内部类与 Lambda 函数比较
public class Demo03Collections { public static void main(String[] args) { //创建集合 List<Student> list = new ArrayList<>(); //添加元素 list.add(new Student("嫐", 20)); list.add(new Student("嬲", 18)); list.add(new Student("挊", 22)); //使用比较器排序对集合中的学生对象根据年龄升序排序 //Collections.sort(list, new Rule()); //使用匿名内部类 Collections.sort(list, new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { return o1.getAge() - o2.getAge(); //使用Lambda表达式 Collections.sort(list, (Student o1, Student o2) -> { return o1.getAge() - o2.getAge(); Collections.sort(list, (o1, o2) -> o1.getAge() - o2.getAge()); System.out.println(list);Lambda 格式
Lambda 表达式的标准格式:
(参数类型 参数名) -> { return 返回值;Lambda 表达式的省略规则:
1. 小括号中的参数类型可以省略。- 2. 如果小括号中只有一个参数,那么可以省略小括号。
- 3. 如果大括号中只有一条语句,那么可以省略大括号,return,分号。
public class Demo04SimpleLambda { //定义方法,使用接口当做参数 public static void method(MyInterface m) { m.printStr("hello"); public static void main(String[] args) { //调用method方法,参数传递MyInterface实现类对象 method(new MyInterface() { @Override public void printStr(String str) { System.out.println(str); //使用Lambda表达式的标准格式。 method((String str) -> { System.out.println(str); //1. 小括号中的参数类型可以省略。 method((str) -> { System.out.println(str); //2. 如果小括号中只有一个参数,那么可以省略小括号。 method(str -> { System.out.println(str); //3. 如果大括号中只有一条语句,那么可以省略大括号,return,分号。 method(str -> System.out.println(str));Lambda 使用条件
Lambda 表达式的使用前提:
可以使用接口当做参数,然后传递 Lambda 表达式(常用),也可以将 Lambda 表达式赋值给一个接口类型的变量。
public class Demo05BeforeLambda { //使用接口当做参数 public static void method(MyInterface m) {//m = s -> System.out.println(s) m.printStr("HELLO"); public static void main(String[] args) { //使用接口当做参数,然后传递Lambda表达式。 //method(s -> System.out.println(s)); //使用匿名内部类方式创建对象 MyInterface m = new MyInterface() { @Override public void printStr(String str) { System.out.println(str); MyInterface m = str -> System.out.println(str); m.printStr("Hello"); }
穹的小叮当
wdl***58111027@163.com
紧张的香瓜 · c++ string utf16 - CSDN文库 23 小时前 |
强健的碗 · basic_string 类 | Microsoft Learn 23 小时前 |
一身肌肉的板栗 · C++类结构体与json相互转换 - Yaronzz - 博客园 23 小时前 |