JAVA前线
互联网技术人思考与分享,欢迎长按关注
JAVA13已经面世一段时间了,但是追根溯源一些新特性例如Lambda表达式、函数式接口、StreamAPI首次还在是出现在JAVA8。这些新特性有些开发者使用并不习惯,尤其链式编程感觉没有代码断句,可读性不强。但是JAVA8之所以逐渐流行确实是因为确实有许多优点:
现在项目代码中越来越多出现JAVA8语法,为了读懂代码也需要我们熟悉JAVA8语法,本文介绍JAVA8如下重要特性,streamAPI我们下一篇文章再详细介绍。
Lambda表达式本质上是一个匿名函数,我们可以将一个Lambda表达式像参数一样进行传递。
public static void test01() {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("公众号JAVA前线");
}
}).start();
/** Lambda表达式 **/
new Thread(() -> System.out.println("公众号JAVA前线")).start();
}
我们看到Lambda表达式将6行代码缩短为1行,代码简洁而优雅,但是仅仅看代码并不好理解,下面我们介绍Lambda语法。
Lambda表达式引入了->箭头操作符,箭头操作符左边指定表达式参数,右表是表达式执行体,下面我们根据参数个数的不同说明Lambda表达式语法。
public static void test02_NoParam() {
Runnable task = () -> System.out.println("公众号JAVA前线");
new Thread(task).start();
}
单个参数可以不写小括号。假设一个方法参数类是字符串,在写Lambda表达式时并不要显示申明String类型,编译器可以根据上下文推断出类型,这就是类型推断。
import java.util.function.Consumer;
public static void test03_OneParam() {
Consumer
c1.accept("公众号JAVA前线");
Consumer
c2.accept("公众号JAVA前线");
}
上述例子使用了函数式接口Consumer,下一个章节我们再介绍。
如果Lambda体只有一行代码则花括号和return可以省略。
public class Student {
private int age;
private String name;
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public static void test04_MultiParam() {
List
Collections.sort(list, new Comparator
@Override
public int compare(Student o1, Student o2) {
return o1.getAge().compareTo(o2.getAge());
}
});
Collections.sort(list, (o1, o2) -> {
return o1.getAge().compareTo(o2.getAge());
});
Collections.sort(list, (o1, o2) -> o1.getAge().compareTo(o2.getAge()));
}
函数式接口特点只包含了一个方法。JAVA8有四大内置函数式接口,其它内置函数式接口,还可以自定义函数式接口。
接口名 | 输入类型 | 输出类型 |
---|---|---|
Consumer[T] | T | void |
Supplier[T] | void | T |
Function[T,R] | T | R |
Predicate[T] | T | boolean |
Consumer作为消费型接口输入类型为T,没有输出类型,核心方法accept(T)
import java.util.function.Consumer;
public static void testConsumer() {
Consumer
String newStr = "公众号" + str;
System.out.println(newStr);
};
consumer.accept("JAVA前线");
}
Supplier作为供给型接口没有输入类型,输出类型为T,核心方法T get()
import java.util.function.Supplier;
public static void testSupplier() {
Supplier
return "公众号JAVA前线";
};
String result = supplier.get();
System.out.println(result);
}
Function作为函数型接口输入类型为T,输出类型为R,核心方法R apply(T)
import java.util.function.Function;
public static void testFunction() {
Function
if("公众号JAVA前线".equals(str)) {
return 1;
}
return 0;
};
Integer result = function.apply("公众号JAVA前线");
System.out.println(result);
}
Predicate作为判断型接口输入类型为T,输出类型为boolean,核心方法boolean test(T)
import java.util.function.Predicate;
public static void testPredicate() {
Predicate
if ("公众号JAVA前线".equals(str)) {
return Boolean.TRUE;
}
return Boolean.FALSE;
};
boolean result = predicate.test("公众号JAVA前线");
System.out.println(result);
}
FunctionalInterface标识一个自定义函数式接口,我们可以根据需求自定义函数式接口。
/**
* 自定义函数接口
*
* @author 公众号JAVA前线
*
* @param
* @param
* @param 输出类型
*/
@FunctionalInterface
public interface MyInterfaceFunction<T, R, U> {
public U bizMethod(T t, R r);
}
public class Java8_Function {
public static void testMyFunction() {
MyInterfaceFunction
if ("公众号".equals(str1) && "JAVA前线".equals(str2)) {
return 1;
}
return 0;
};
Integer result = myFuntion.bizMethod("公众号", "JAVA前线");
System.out.println(result);
}
}
在四大内置函数式接口基础上,JAVA8提供了其它内置函数式接口,我们尝试列出一些并选择编写几个代码实例。
接口名 | 输入类型 | 输出类型 |
---|---|---|
BiConsumer | T、U | void |
BiFunction | T、U | R |
UnaryOperator | T | T |
BinaryOperator | T、T | T |
ToIntFunction | T | int |
BiFunction是Function函数增强版,允许两种输入类型
import java.util.function.BiFunction;
public static void testBiFunction() {
BiFunction
if ("公众号".equals(str1) && "JAVA前线".equals(str2)) {
return 1;
}
return 0;
};
Integer result = biFunction.apply("公众号", "JAVA前线");
System.out.println(result);
}
BiConsumer是Consumer函数增强版本,允许两种输入类型
import java.util.function.BiConsumer;
public static void testBiConsumer() {
BiConsumer
System.out.println(str1 + str2);
};
biConsumer.accept("公众号", "JAVA前线");
}
对类型为T的数据进行二元运算,并返回类型为T的结果
import java.util.function.BinaryOperator;
public static void testBinaryOperator() {
BinaryOperator
return str1 + str2;
};
String result = biOperator.apply("公众号", "JAVA前线");
System.out.println(result);
}
方法引用语法操作符是两个冒号,初看会让人比较费解。本章节我们来分析这个语法。当我们在编写Lambda方法体时,如果方法体的方法已经有实现,那么我们可以直接引用这个方法,这就是方法引用,需要注意的是参数列表必须一致。方法引用语法有四类:
public class Student {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public static void test01() {
Consumer
c1.accept("公众号JAVA前线");
Consumer
c2.accept("公众号JAVA前线");
Student student = new Student("公众号JAVA前线");
Supplier
System.out.println(s1.get());
Supplier
System.out.println(s2.get());
}
public class Student {
private int age;
private String name;
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public static void test02() {
BiPredicate
System.out.println(bp1.test("公众号", "JAVA前线"));
// 类::实例方法
BiPredicate
System.out.println(bp2.test("公众号", "JAVA前线"));
List
Collections.sort(list, new Comparator
@Override
public int compare(Student o1, Student o2) {
return o1.getAge().compareTo(o2.getAge());
}
});
Collections.sort(list, (o1, o2) -> o1.getAge().compareTo(o2.getAge()));
// 类::实例方法
Collections.sort(list, Comparator.comparing(Student::getAge));
}
public class Student {
private int age;
private String name;
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public static int compareAge(Student s1, Student s2) {
return s1.getAge().compareTo(s2.getAge());
}
}
public static void test03() {
List
Collections.sort(list, new Comparator
@Override
public int compare(Student o1, Student o2) {
return o1.getAge().compareTo(o2.getAge());
}
});
Collections.sort(list, (o1, o2) -> o1.getAge().compareTo(o2.getAge()));
Collections.sort(list, Comparator.comparing(Student::getAge));
// 类::静态方法
Collections.sort(list, Student::compareAge);
}
public class Student {
private String name;
public Student(String name) {
this.name = name;
}
}
public static void test04() {
Function
System.out.println(f1.apply("公众号JAVA前线"));
Function
System.out.println(f2.apply("公众号JAVA前线"));
Function
System.out.println(f3.apply(15));
Function
System.out.println(f4.apply(15));
Supplier> s1 = () -> new ArrayList
System.out.println(s1.get());
Supplier> s2 = ArrayList
System.out.println(s2.get());
}
本文我们总结了Lambda表达式,函数式接口,方法引用语法,这些语法相较于传统语法改变不小,一开始并不容易理解,还需要反复实践。下一篇文章我们介绍JAVA8强大的StreamAPI语法请继续关注。
JAVA前线
互联网技术人思考与分享,欢迎长按关注