Lambda 表达式
Java 8新特性简介
- 速度更快
- 代码更少(增加了新的语法 Lambda 表达式)
- 强大的 Stream API
- 便于并行
- 最大化减少空指针异常 Optional
为什么使用Lambda 表达式
Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码 像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使 Java的语言表达能力得到了提升。
从匿名类到 Lambda 的转换
// jdk 1.7 前 ,必须是 final
int num = 0;
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println(" Hello Lambda !!!"/* +num++*/);
}
};
runnable.run();
System.out.println("__________________________________");
Runnable runnable1 = () -> System.out.println(" Hello Lambda !!!"/*,num++*/);
runnable1.run();
/**
* 匿名内部类
*/
@Test
public void test() {
Comparator<Integer> comparator = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1, o2);
}
};
TreeSet<Integer> treeSet = new TreeSet<>(comparator);
}
/**
* Lambda
*/
@Test
public void test2() {
Comparator<Integer> comparator = (x, y) -> Integer.compare(x, y);
Comparator<Integer> comparator2 = Integer::compare;
TreeSet<Integer> treeSet = new TreeSet<>(comparator);
}
Lambda 表达式语法
Lambda 表达式在Java 语言中引入了一个新的语法元 素和操作符。这个操作符为 “->” , 该操作符被称 为 Lambda 操作符或剪头操作符。它将 Lambda 分为 两个部分:
左侧:指定了 Lambda 表达式需要的所有参数
右侧:指定了 Lambda 体,即 Lambda 表达式要执行 的功能
代码演示
package com.www.java8.test;
import com.www.java8.inter.MyFun;
import com.www.java8.inter.MyFunction2;
import org.testng.annotations.Test;
import java.util.*;
import java.util.function.Consumer;
/**
* 一 、Lambda 表达式的基础语法 :Java8 中引入图了一个新的操作符 ” -> “ 该操作符称为箭头操作符 或 Lambda 操作符
* <p>
* 箭头操作符将 Lambda分成了两部分
* <p>
* 右侧 : Lambda 表达式的参数列表
* <p>
* 左侧 : Lambda 表达式中所需执行的功能, 即 Lambda 体
* <p>
* <p>
* 语法格式一 : 无参数 , 无返回值
* <p>
* () -> System.out.println("Hello Lambda !!")
* <p>
* <p>
* 语法格式二 : 有一个参数 ,无返回值
* <p>
* (x)->System.out.println(x)
* <p>
* <p>
* 语法格式三 : 若只有一个参数,小括号可以省略不写
* <p>
* x -> System.out.println(x)
* <p>
* <p>
* 语法格式四 :有两个以上的参数, 有返回值 ,并且 Lambda 体中 有多条语句
* <p>
* <pre>
* Comparator<Integer> comparator = (x, y) -> {
* System.out.println("函数式接口!!!");
* return Integer.compare(x, y);
* };
* </pre>
* <p>
* <p>
* 语法格式五 : 若 Lambda 体中只有一条语句, return 和 大括号 都可以省略不写
* <p>
* <pre>
* Comparator<Integer> comparator = (x, y) -> Integer.compare(x, y);
* Comparator<Integer> comparator1 = Integer::compare;
* </pre>
* <p>
* <p>
* 语法格式六: Lambda 表达式的参数列表的数据类型可以省略不写, 因为 JVM 编译器 可以通过上下文推断出 数据类型, 即 ”类型推断“
* <p>
* Comparator<Integer> comparator = (Integer x, Integer y) -> Integer.compare(x, y);
* <p>
* <p>
* <p>
* 上联 : 左右遇一括号省
* 下联 : 左侧推断类型省
* 横批 : 能省则省
* <p>
* <p>
* <p>
* 二: Lambda 表达式需要 ”函数式接口“ 的支持
* <p>
* 函数式接口: 接口中只有一个抽象方法的接口,称为函数式接口, 可以使用 注解 @FunctionalInterface 修饰
* 可以检查是否为函数式接口
*
* @author Www
* <p>
* 邮箱: 483223455@qq.com
* <p>
* 创建时间: 2022/8/11 17:03 星期四
* <p>
*/
public class Lambda1Test {
/**
* 语法格式一 : 无参数 , 无返回值
* <p>
* () -> System.out.println("Hello Lambda !!")
*/
@Test
public void test1() {
// jdk 1.7 前 ,必须是 final
int num = 0;
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println(" Hello Lambda !!!"/* +num++*/);
}
};
runnable.run();
System.out.println("__________________________________");
Runnable runnable1 = () -> System.out.println(" Hello Lambda !!!"/*,num++*/);
runnable1.run();
}
/**
* 语法格式二 : 有一个参数 ,无返回值
* <p>
* (x)->System.out.println(x)
*/
@Test
public void test2() {
Consumer<String> consumer = (x) -> System.out.println(x);
Consumer<String> consumer1 = System.out::print;
consumer1.accept("www");
}
/**
* 语法格式四 :有两个以上的参数, 有返回值 ,并且 Lambda 体中 有多条语句
* <p>
* <pre>
* Comparator<Integer> comparator = (x, y) -> {
* System.out.println("函数式接口!!!");
* return Integer.compare(x, y);
* };
* </pre>
*/
@Test
public void test3() {
Comparator<Integer> comparator = (x, y) -> {
System.out.println("函数式接口!!!");
return Integer.compare(x, y);
};
int compare = comparator.compare(1, 2);
System.out.println(compare);
}
/**
* 语法格式五 : 若 Lambda 体中只有一条语句, return 和 大括号 都可以省略不写
* <p>
* <pre>
* Comparator<Integer> comparator = (x, y) -> Integer.compare(x, y);
* Comparator<Integer> comparator1 = Integer::compare;
* </pre>
*/
@Test
public void test4() {
Comparator<Integer> comparator = (Integer x, Integer y) -> Integer.compare(x, y);
Comparator<Integer> comparator1 = Integer::compare;
int compare = comparator1.compare(1, 333);
System.out.println(compare);
}
/**
* 类型推断 ---> jdk 1.8 出现; 1.7 之前不存在
*/
@Test
public void test5() {
String str[] = {"w", "ww", "www"};
String str1;
// str1={"www","ww","w"};
List<String> list = new ArrayList<>();
show(new HashMap<>());
}
public void show(Map<String, Integer> map) {
System.out.println(map.toString());
}
/**
* 对一个数进行运行算
*/
@Test
public void test6() {
Integer operation = operation(46, x -> x * x);
System.out.println(operation);
System.out.println(operation(919, x -> x * x));
}
/**
* 运算方法
*
* @param num
* @param fun
* @return
*/
public Integer operation(Integer num, MyFun<Integer> fun) {
return fun.getValue(num);
}
/**
*
*/
@Test
public void test7() {
oop(46L, 919L, Long::sum);
oop(46L, 919L, (x, y) -> x * y);
}
/**
* 对两个 Long 类型进行处理
*
* @param l1
* @param l2
* @param fun
*/
public void oop(Long l1, Long l2, MyFunction2<Long, Long> fun) {
System.out.println(fun.getValue(l1, l2));
}
}
image.png
image.png
类型推断
上述 Lambda 表达式中的参数类型都是由编译器推断 得出的。Lambda 表达式中无需指定类型,程序依然可 以编译,这是因为 javac 根据程序的上下文,在后台 推断出了参数的类型。Lambda 表达式的类型依赖于上下文环境,是由编译器推断出来的。这就是所谓的 “ 类型推断"