本節是lambda表達式的一個入門課,講解的同時配有練習demo
前言什么是lambda表達式?基礎語法函數式接口自己實現一個函數式接口jdk提供的函數式接口ConsumersupplierfunctionPredicate其他場景
前言
lambda表達式是java8推出的一個新特性。標志着從jdk1.8開始,java正式支持函數式編程。使用lambda表達式可以用簡潔流暢的代碼完成一個功能,這也在一定程度上,可以減輕了java一直為人詬病的代碼簡潔性問題。
什么是lambda表達式?
lambda表達式可以簡單理解為一段可以傳遞的代碼,核心思想是將面向對象中傳遞數據變為傳遞行為。下面舉一個編寫線程的例子。
1Runnable runnable = new Runnable() {
2 @Override
3 public void run() {
4 System.out.println("hello lambda");
5 }
6};
這里使用的是匿名內部類的方式。匿名內部類實現的也是將代碼作為數據傳遞,不過使用匿名內部類還是不夠簡潔,那么使用lambda表達式的代碼是什么樣的呢?
1Runnable runnable = () -> System.out.println("hello lambda");
我們可以看到使用lambda表達式實現起來非常的簡單,只需要一行代碼即可,接下來我們就試着分析一下這段代碼。
基礎語法

我們可以將lambda表達式整體看作是一個函數,()存放的是函數的操作數 ->指向的是函數的邏輯,可以用{}包裹起來。
函數式接口
我們可以看到上述的示例代碼,lambda表達式的引用變量是一個runnable類型,事實上,java為我們提供了多種變量類型供我們選擇,這些類型我們稱之為函數式接口。
函數式接口是只有一個方法的接口,用作lambda表達式的類型。比如我們之前提到的Runnable接口
1@FunctionalInterface
2public interface Runnable {
3 /**
4 * When an object implementing interface <code>Runnable</code> is used
5 * to create a thread, starting the thread causes the object's
6 * <code>run</code> method to be called in that separately executing
7 * thread.
8 * <p>
9 * The general contract of the method <code>run</code> is that it may
10 * take any action whatsoever.
11 *
12 * @see java.lang.Thread#run()
13 */
14 public abstract void run();
15}
我們可以看到interface上一個注解@FunctionInterface,它的作用是告訴編譯器這個接口是一個函數式接口。
自己實現一個函數式接口
我們可以自己實現一個函數式接口,判斷數據的數據是否合法
1/**
2 * 自定義函式數接口
3 *
4 * @author jialin.li
5 * @date 2020-03-18 14:22
6 */
7@FunctionalInterface
8public interface CustomFunctionInterface<T> {
9 boolean legal(T t);
10}
測試方法:
1/**
2 * 測試.
3 *
4 * @author jialin.li
5 * @date 2020-03-18 14:23
6 */
7public class Test {
8
9 public boolean legal(int value, CustomFunctionInterface<Integer> functionInterface){
10 return functionInterface.legal(value);
11 }
12
13 public static void main(String[] args) {
14 System.out.println(new Test().legal(-8, (x) -> x >= 0));
15 }
16}
測試結果:
1false
jdk提供的函數式接口
jdk在java.util.function中為我們提供了非常豐富的函數式接口,大致可以分為4類:

接下來我們會針對這四種不同的接口,給出相應的demo,你也可以先看題目,自己嘗試寫一下
Consumer
將輸入的10進制數,轉換為2進制數輸出
1public void toBinaryString(int value, Consumer<Integer> consumer){
2 consumer.accept(value);
3}
4
5public static void main(String[] args) {
6 new Test().toBinaryString(15, (x) -> System.out.println(Integer.toBinaryString(x)));
7}
supplier
生成n個隨機數100以內的隨機數,以數組的形式返回
1public int[] getRandomArr(int n, Supplier<Integer> supplier) {
2 int[] arr = new int[n];
3 for (int i = 0; i < n; i++) {
4 arr[i] = supplier.get();
5 }
6 return arr;
7}
8
9public static void main(String[] args) {
10 int[] arr = new Test().getRandomArr(10, () -> new Random().nextInt(100));
11 System.out.println(Arrays.toString(arr));
12}
function
生成一個[1,n]組成的階乘數組,例如輸入3,返回[1,4,9]
1public int[] getFactorialArr(int n, Function<Integer,Integer> function) {
2 int[] arr = new int[n];
3 for (int i = 1; i <= n; i++) {
4 arr[i - 1] = function.apply(i);
5 }
6 return arr;
7}
8
9public static void main(String[] args) {
10 int[] arr = new Test().getFactorialArr(10, (x) -> x*x);
11 System.out.println(Arrays.toString(arr));
12}
Predicate
判斷一個數是否是偶數
1public boolean isEven(int n, Predicate<Integer> predicate) {
2 return predicate.test(n);
3}
4
5public static void main(String[] args) {
6 boolean isEven = new Test().isEven(1102, (x) -> (x % 2 == 0));
7 System.out.println(isEven);
8}
其他場景
除了上述的4個接口,java.util.function中還有許多其他的接口,可以實現各種功能。比如實現2個數的加法運算:
1public static void main(String[] args) {
2 BinaryOperator<Integer> binaryOperator = Integer::sum;
3 System.out.println(binaryOperator.apply(1, 3));
4}
實現List遍歷:
1public static void main(String[] args) {
2 List<String> list = new ArrayList<>(Arrays.asList("java", "python", "go", "sql"));
3 list.forEach(System.out::println);
4}
更多場景還請您去探索,感受函數式編程的魅力吧
最后,期待您的訂閱和點贊,專欄每周都會更新,希望可以和您一起進步,同時也期待您的批評與指正!
