前序:
1:Lambda 表达式 及支持 jdk 8 或以上 版本。
2:学习 Lambda 表达式需要了解 “函数式接口”。
3:用过Idea 编辑器的朋友应该知道,idea 已经支持 lambda 表达式,即使你和我一样还不了解 Lambda表达式 ,你若代码中出现了可以更改成Lambda表达式的代码,idea会自动提示你。
4:即便支持就更要学习一下,要不然你会和我一样闹出笑话(真人真事)。
讲个笑话,最开始接触idea(eclipse 转 idea) 的时候,用Runnable 时,idea 出现黄色警告⚠,那是我第一次接触Lamdba 表达式,当时就很好奇跟同事讲 idea 居然可以这样写。现在想起那个同事的表情,就知道他当时为什么不理我了。
Lambda 表达式基础语法总结:
- 语法格式一:无参,无返回值
语法:() -> 具体的实现
演示对象:我们拿 Runable 来演示
- 传统代码
- Lambda 表达式:有没有眼前一亮,是不是很简单。
/**
* 测试
* @param args
*/
public static void main(String[] args) {
Runnable runnable=new Runnable() {
@Override
public void run() {
System.out.println("传统方式 无参,无返回值");
}
};
runnable.run();
}
// 运行结果
传统方式 无参,无返回值
/**
* 测试
* @param args
*/
public static void main(String[] args) {
Runnable runnable= () -> System.out.println("Lambda 无参,无返回值");
runnable.run();
}
//运行结果
Lambda 无参,无返回值
- 语法格式二:有一个参数,并且无返回值
语法:(x)-> 具体的实现
演示对象:自定义 ”函数式接口“
与上面不同:这里有了一个 x ,x:表示参数,
- 自定义一个”函数式接口”
- Lambda 表达式实现:这里的 x 表示形参,是calculate方法 传进来的 10,你也可以不取名为x , 其它的都可以。
/**
* @author Administrator
* @version 1.0
* @describe
* @date 2019/12/21 20:23
*/
@FunctionalInterface
public interface FunctionTest {
/**
* 用于对这个数值 进行处理,
* 交由 子类实现。
* @param num
*/
void calculate(int num);
}
/**
* 测试
* @param args
*/
public static void main(String[] args) {
//需求:打印一个数值中的偶数
FunctionTest test =(x) ->{
for (int i = 0; i < x; i++) {
if (i % 2 == 0) {
System.out.println(i);
}
}
};
test.calculate(10);
}
// 运行结果
0
2
4
6
8
- 语法格式三:若有一个参数,小括号省略不写
x -> 具体的实现
演示对象:用 语法格式二 来做演示
代码演示:忽略 x 的小括号,
/** * 测试 * @param args */ public static void main(String[] args) { //需求:打印一个数值中 2的倍数 FunctionTest test = x ->{ for (int i = 0; i < x; i++) { if (i % 2 == 0) { System.out.println(i); } } }; test.calculate(10); } #运行结果 0 2 4 6 8
- 语法格式四:若存在多个参数、多条语句时,那么必须 带 {}。
(x,y) ->{具体的实现}
演示对象:自定义” 函数接口 “,
强调:若存在多个参数时,必须带上"小括号",取什么名无所谓,不重复即可。
- 自定义”函数接口“
- Lambda 表达式实现方式一:计算两个数的和
/**
* @author Administrator
* @version 1.0
* @describe
* @date 2019/12/21 20:23
*/
@FunctionalInterface
public interface FunctionTest {
/**
* 用于对两个数值 进行处理,
* 交由 子类实现。
* @param num1
* @param num2
*/
void calculate(double num1,double num2);
}
/**
* 测试
* @param args
*/
public static void main(String[] args) {
//需求:打印一个数值中 2的倍数
FunctionTest test = (x,y) -> System.out.println(String.format("%s + %s = %s",x,y,x+y));
test.calculate(5,3);
}
// 运行结果
5.0 + 3.0 = 8.0
- Lambda 表达式实现方式二:计算两个数的 积
/**
* 测试
* @param args
*/
public static void main(String[] args) {
//需求:打印一个数值中 2的倍数
FunctionTest test = (x,y) -> System.out.println(String.format("%s x %s = %s",x,y,x*y));
test.calculate(4,6);
}
// 运行结果
4.0 x 6.0 = 24.0
- Lambda表达式实现方式三:上面都是 单条语句的,下面实现多条语句,分别输出两个参数的值就行了。
/**
* 测试
* @param args
*/
public static void main(String[] args) {
//需求:打印一个数值中 2的倍数
FunctionTest test = (x,y) ->{
System.out.println(String.format("x = %s",x));
System.out.println(String.format("y = %s",y));
};
test.calculate(4,6);
}
//运行结果
x = 4.0
y = 6.0
- 传统方式实现:
第一种方式:创建一个子类由子类来实现。
这里就不介绍 第一种方式了,太麻烦还得创建一个新的类。
第二种方式:采用匿名内部类的方式进行实现。
- 采用 匿名内部类的方式进行实现两个数(4 和 5)的和
public static void test(double x,double y,FunctionTest test){
test.calculate(x,y);
}
/**
* 测试
* @param args
*/
public static void main(String[] args) {
//匿名内部类的方式进行实现
test(4, 5, new FunctionTest() {
@Override
public void calculate(double num1, double num2) {
System.out.println(num1* num2);
}
});
}
// 运行结果:
20.0
5. 语法格式五:若存在多个参数、单条语句时,return 或 {} 可以省略不写。
- 代码上面已经演示过了,但是上面的案例都是无返回值的,那么看看有返回值的情况下是怎么样的
- 更改一下 接口方法。
/**
* @author Administrator
* @version 1.0
* @describe
* @date 2019/12/21 20:23
*/
@FunctionalInterface
public interface FunctionTest {
/**
* 用于对这个数值 进行处理,
* 交由 子类实现。
* @param num1
* @param num2
*/
double calculate(double num1,double num2);
}
- 代码演示 有返回值的 Lambda 表达式
/**
* 测试
* @param args
*/
public static void main(String[] args) {
FunctionTest test=(x,y) ->{
double result = x * y;
return result;
};
System.out.println(test.calculate(10,2));
}
# 运行结果
20.0
6. 语法格式六:Lambda 表示的参数列表的参数类型可以省略不写,因为JVM编辑器通过上下文推断出,数据类型,即“类型推断”。
JAVA 内置四大核心 函数接口
上面的案例中,每写一个案例,都需要自己创建一个 “函数接口”,在java 中已经为我们内置好了一些“函数接口”,对于一些普通的操作,我们就无需再自己去创建接口。但是面对比较复杂的业务时,还是需要我们自己来创建的。
只要这四大函数接口能充分掌握了,那么其他的也就水到渠成了。
- 四大核心 函数接口 分类
名称 | 定义 | 方法 | 解释 |
Consumer<T> | 消费型接口 | void accept(T t); | 消费型接口,主要用于做一些无返回值数据处理,最简单的案例就是 在里面输出一句话 System.out.println("hello word!")。 |
Supplier<T> | 供给型接口 | T get() | 供给型接口,主要是用于提供一些资源响应。如Random.nextInt()方法,它就是产生一些随机数并返回。默默的奉献着,不收取人任何回报。 |
Function<T,R> | 函数型接口 | R apply(T t) | 函数型接口,有两个参数(T、R),对 T 进行处理,返回 R。 |
Predicate<T> | 断言型接口 | boolean test(T t) | 主要用于做一些判断型操作。 |
- Consumer 案例演示
/**
* 测试
* @param args
*/
public static void main(String[] args) {
List<Integer> numbers=new ArrayList<>();
numbers.add(52);
numbers.add(18);
numbers.add(45);
numbers.add(12);
numbers.add(63);
//案例: 将上列数据 按照 升序进行排列
Consumer<List<Integer>> consumer=(t)->{
int size = numbers.size();
for (int i = 0; i < size-1; i++) {
for (int j = 0; j < size-1-i; j++) {
//比较两个整数的大小
if (numbers.get(j)>numbers.get(j+1)) {
Integer temp = numbers.get(j);
// 使用list集合的set方法,找到位置并将数字赋值到该位置
numbers.set(j, numbers.get(j+1));
numbers.set(j+1,temp);
}
}
}
};
consumer.accept(numbers);
for (int i = 0; i < numbers.size(); i++) {
System.out.println(numbers.get(i));
}
}
- Consumer 案例结果
12
18
45
52
63
- 也可以这样实现。
/**
* 测试
* @param args
*/
public static void main(String[] args) {
List<Integer> numbers=new ArrayList<>();
numbers.add(52);
numbers.add(18);
numbers.add(45);
numbers.add(12);
numbers.add(63);
sort(numbers,(t)->{
int size =numbers.size();
for (int i = 0; i < size-1; i++) {
for (int j = 0; j < size-1-i; j++) {
//比较两个整数的大小
if (numbers.get(j)>numbers.get(j+1)) {
Integer temp = numbers.get(j);
// 使用list集合的set方法,找到位置并将数字赋值到该位置
numbers.set(j, numbers.get(j+1));
numbers.set(j+1,temp);
}
}
}
});
//打印 排序后的结果
System.out.println(numbers);
}
// 自定义方法,这样的方式会更加灵活,
public static void sort(List<Integer> list, Consumer consumer){
consumer.accept(list);
}
// 运行结果
[12, 18, 45, 52, 63]
- Supplier 案例演示:
需求:根据用户输入条件 匹配 用户信息并返回。
如:用户输入 一个 数据 16,那么匹配用户集合中包含 16 的数据信息。并做返回。
定义一个 三条用户数据信息,存放到 集合中。
然后 采用 Supplier 供给型函数接口 实现数据匹配。
/**
* 测试 定义一个map list 模拟 用户信息,
* @param args
*/
public static void main(String[] args) {
List<Map<String,String>> nameList=new ArrayList<>();
Map<String,String> user1=new HashMap<>(5);
user1.put("姓名","张三");
user1.put("年龄","18");
user1.put("性别","男");
nameList.add(user1);
Map<String,String> user2=new HashMap<>(5);
user2.put("姓名","春丽");
user2.put("年龄","16");
user2.put("性别","女");
nameList.add(user2);
Map<String,String> user3=new HashMap<>(5);
user3.put("姓名","小明");
user3.put("年龄","16");
user3.put("性别","男");
nameList.add(user3);
//根据 数据为16 的用户信息
List< Map<String,String>> maps= queryUserName( nameList,()->"16");
System.out.println(maps);
}
/**
* 根据用户输入条件,匹配用户信息并返回
* @param mapList
* @param supplier
* @return
*/
public static List< Map<String,String>> queryUserName( List<Map<String,String>> mapList,Supplier<String> supplier){
List< Map<String,String>> mapList1=new ArrayList<>();
for (int i = 0; i < mapList.size(); i++) {
Map<String,String> map=mapList.get(i);
for (String key: map.keySet()){
if (map.get(key).equals(supplier.get())) {
mapList1.add(map);
continue;
}
}
}
return mapList1;
}
- Supplier 案例 运行结果:
//包含 16 的数据 有 两条
[{姓名=春丽, 年龄=16, 性别=女}, {姓名=小明, 年龄=16, 性别=男}]
- 若上面的案例太复杂,可以简单的使用 Supplier :实际上在工作中,肯定不会这么写(如下),业务肯定这个复杂,一个复杂 一个简单的对比,只是想说明 supplier 的作用。更想说明 Lambda 表达式的好处。
/**
* 测试
* @param args
*/
public static void main(String[] args) {
//生成一个 随机数
Supplier supplier =() -> new Random().nextInt();
System.out.println(supplier.get());
}
// 运行结果
1144876318
- Function 案例展示:
需求:对字符串进行处理。
/**
* 测试
* @param args
*/
public static void main(String[] args) {
//小写处理
String toLowerCase = strHandler("Hello, Word!",(t)-> t.toLowerCase() );
System.out.println(toLowerCase);
//大写处理
String toUpperCase = strHandler("Hello, Word!",(t)-> t.toUpperCase() );
System.out.println(toUpperCase);
}
/**
* 对字符串进行处理
* @param str
* @param function
* @return
*/
public static String strHandler(String str, Function<String,String> function){
return function.apply(str);
}
- Function 案例 运行结果:
hello, word!
HELLO, WORD!
- Predicate 案例展示:
检测 用户是否输入的是数字
/**
* 测试
* @param args
*/
public static void main(String[] args) {
// 测试数据
String str= "12";
boolean bool= numberVerification(str,(s)->{
Pattern pattern = Pattern.compile("^-?\\d+(\\.\\d+)?$");
Matcher isNum = pattern.matcher(s);
if (!isNum.matches()) {
return false;
}
return true;
});
System.out.println(bool);
}
/**
* 检测用户输入是否为数字
* @param str
* @param predicate
* @return
*/
public static boolean numberVerification(String str, Predicate<String> predicate){
return predicate.test(str);
}
- Predicate 案例运行结果:
true
最后总结:
说实话,我案例表述的不是很明白,若你想要好好的学习一下 Lambda 表达式 建议 去 B站 找视频系统学习。以上案例 都是我看视频时,练手用的代码。至于质量而已,我能明白就行了,我又不是行业大佬,也没想过能写出高质量博客,只是记录一下我的学习过程罢了。
你看了,有所感悟,我也很高兴,若是没有帮助,关掉就行了。
后续更新中....