茂展的分享博客

Java8——Lambda表达式

Java8——Lambda表达式

语法糖指的是使用更方便,但原理不变的代码语法

lambda表达式

java8有一个词汇不得不提,就是 函数式接口
函数式接口:有且只有一个抽象方法的接口,我们可以在接口上标注@FunctionalInterface,表示是一个函数式接口,主要作为参数或者返回值使用

1
2
3
4
5
6
7
package cn.itcast.helloworld.java8;

@FunctionalInterface
public interface MyFunc {

public abstract void save();
}

lambda表达式的重要特征:

  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
  • 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
  • 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。

注:借鉴菜鸟教程,感觉总结特别好

接下来展示一个小demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static void save(MyFunc myFunc){
myFunc.save();
}


public static void main(String[] args) {
//传递接口的匿名内部类
save(new MyFunc() {
@Override
public void save() {
System.out.println("执行完成");
}
});

//由于方法的参数是一个函数式接口,所以可以使用lambda表达式
save(()->{
System.out.println("lambda表达式的使用");
});

//由于函数式接口的方法没有参数,而且只有一条执行语句
save(()->System.out.println("lambda表达式的使用"));
}

lambda表达式是延迟执行,可以对代码执行结果不急用用lambda语法,有助于提高性能
lambda执行的前提是必须有函数式接口
我们做了一个demo最适合解释lambda表达式的用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
* 我们做了这么一个案例:
* 当level的值为1的时候,打印日志,
* 其他都不打印,为了防止我们苦费心思拿到日志之后,结果level不为 1,就损耗了性能
* 所以我们使用有延迟加载作用的lambda
*
* */
public class Demo {

public static void save(int level,MyFunc myFunc){
if(level == 1) myFunc.printLog();
}


//只有level的数字是1的时候,lambda表达式才会执行
public static void main(String[] args) {

save(1,()-> System.out.println("这是日志"));
}

}

Java中也给我们提供弄了很多函数式接口

Comparator比较型接口

在java中,Comparator接口是个函数式接口,内部只有一个抽象方法,所以按照lambda表达式规则,可以这样写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class MyCompare {

public static Comparator<String> myComparator(){
//匿名内部类
// return new Comparator<String>() {
// @Override
// public int compare(String o1, String o2) {
// return o2.length()-o1.length();
// }
// };
//采用Lambda表达式
return (o1,o2)->o2.length()-o1.length();
}

public static void main(String[] args) {
String[] arrList = {"aaaaa","b","cccc","dddd"};
System.out.println("原先顺序:"+Arrays.toString(arrList));

Arrays.sort(arrList,myComparator());
System.out.println("现在顺序:"+Arrays.toString(arrList));
}
}

生产型接口指的是接口的泛型是什么类型,那么接口最后的返回值就是什么类型

Supplier生产型接口

1
2
3
4
5
6
7
8
9
10
11
12
13
import java.util.function.Supplier;

public class ProduceInterface {

public static String myPrint(Supplier<String> supplier){
return supplier.get();
}

public static void main(String[] args) {
String str = myPrint(()->"李茂展");
System.out.println(str);
}
}

Consumer消费型接口

消费型接口,指的是泛型执行什么类型,就可以消费什么类型的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.util.function.Consumer;

public class ConsumerInterface {

public static void myConsumer(String name, Consumer<String> consumer){
consumer.accept(name);
}

public static void main(String[] args) {
//我们实现翻转输出
myConsumer("李茂展",(name)->{
String nameReverse = new StringBuffer(name).reverse().toString();
System.out.println(nameReverse);
});
}
}

Consumer中有一个默认方法andThen,我们可以这样使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.util.function.Consumer;

public class ConsumerInterface {

public static void myConsumer(String name, Consumer<String> consumer1, Consumer<String> consumer2){
//谁写在前面谁先消费
consumer1.andThen(consumer2).accept(name);
}

public static void main(String[] args) {
//我们实现先大写后小写输出
myConsumer("Tom",(name)-> System.out.println(name.toUpperCase()),(name)->
System.out.println(name.toLowerCase()));
}
}

Predicate判断型接口

predicate是用于判断的函数式接口,内部有一个test抽象方法,返回值是bool类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.util.function.Predicate;

public class PredicateInterface {

public static boolean myPredicate(String str, Predicate<String> predicate){
return predicate.test(str);
}

public static void main(String[] args) {
String str = "abcdefg";
boolean bool = myPredicate(str, (str1) -> str1.length() > 5);
System.out.println(bool);
}
}

predicate有三个默认方法:

  • and: 表示条件同时满足
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.util.function.Predicate;

public class PredicateInterface {

public static boolean myPredicate(String str, Predicate<String> predicate1,Predicate<String> predicate2){
return predicate1.and(predicate2).test(str);
}

public static void main(String[] args) {
String str = "abcdefg";
//判断长度大于5并且包含f字母,结果输出为true
boolean bool = myPredicate(str, (str1) -> str1.length() > 5,(str1) -> str1.contains("f"));
System.out.println(bool);
}
}
  • or: 表示条件只需要满足一个就可以返回true
    和上面的代码差不多相同,区别就是把上面的and替换成or,return predicate1.or(predicate2).test(str);
  • negate: 表示取反
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.util.function.Predicate;

public class PredicateInterface {

public static boolean myPredicate(String str, Predicate<String> predicate){
return predicate.negate().test(str);
}

public static void main(String[] args) {
String str = "abcdefg";
//判断长度大于5,然后结果应该是true,由于加上了negate,所以结果是false
boolean bool = myPredicate(str, (str1) -> str1.length() > 5);
System.out.println(bool);
}
}

Function转换型接口

Function中最主要的抽象方法是apply(T,t),T表示转换前的类型,t表示转换后的类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.util.function.Function;

public class MyFunction {

public static void myFunc(String str, Function<String,Integer> function){

Integer val = function.apply(str);
System.out.println(val);
}

public static void main(String[] args) {
//使用lambda表达式把字符串 "123"输出为数字 123
myFunc("123",(str)->Integer.parseInt(str));
}
}

Function有个默认方法andThen

1
2
3
4
5
6
7
8
9
10
11
12
13
public class MyFunction {

public static void myFunc(String str, Function<String,Integer> function1,Function<Integer,String> function2){

String str_val = function1.andThen(function2).apply(str);
System.out.println(str_val);
}

public static void main(String[] args) {
//使用lambda表达式把字符串转成数字然后再加上10再转换为字符串
myFunc("123",(str)->Integer.parseInt(str),(val)->String.valueOf(val +=10));
}
}


------本文结束感谢阅读------
🐶 您的支持将鼓励我继续创作 🐶