Lambda8 表達式

Lambda 表達式

Lambda 表達式是 JDK8 的一個新特性,可以取代大部分的匿名內部類,寫出更優雅的 Java 代碼,尤其在集合的遍歷和其他集合操作中,可以極大地優化代碼結構。
JDK 也提供了大量的內置函數式接口供我們使用,使得 Lambda 表達式的運用更加方便、高效。

可以對某些匿名內部類的寫法進行簡化,它是函數式編程思想的一個重要體現,不用關注是什麼對象,而是更關注對數據進行了什麼操作。

基本格式

(參數列表)->{代碼}

範例

範例一:

在創建線程並啓動時可以使用匿名內部類的寫法;

  • 匿名內部類方式:
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println(Thread.currentThread());
    }
}).start();
  • Lambda方式:
new Thread(() -> {
    System.out.println(Thread.currentThread());
}).start();

範例二:

IntBinaryOperator是一個接口,使用匿名內部類的寫法調用該方法;

  • 匿名內部類方式:
public static int calculateNum(IntBinaryOperator operator) {
    int a = 10;
    int b = 20;
    return operator.applyAsInt(a, b);
}

@Test
public void testLambda2() {
    int i = calculateNum(new IntBinaryOperator() {
        @Override
        public int applyAsInt(int left, int right) {
            return left + right;
        }
    });

    System.out.println(i);
}
  • Lambda方式:
public static int calculateNum(IntBinaryOperator operator) {
    int a = 10;
    int b = 20;
    return operator.applyAsInt(a, b);
}

@Test
public void testLambda2() {
    int i = calculateNum((int left, int right) -> {
        return left + right;
    });

    System.out.println(i);
}

範例三:

IntPredicate是一個接口。先使用匿名內部類的寫法調用該方法;

  • 匿名內部類方式:
public static void printNum(IntPredicate predicate) {
    int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    for (int i : arr) {
        if (predicate.test(i)) {
            System.out.println(i);
        }
    }
}

@Test
public void testLambda3() {
    printNum(new IntPredicate() {
        @Override
        public boolean test(int value) {
            return value % 3 == 0;
        }
    });
}
  • Lambda方式:
public static void printNum(IntPredicate predicate) {
    int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    for (int i : arr) {
        if (predicate.test(i)) {
            System.out.println(i);
        }
    }
}

@Test
public void testLambda3() {
    printNum((int value) -> {
        return value % 3 == 0;
    });
}

範例四:

Function是一個接口,先使用匿名內部類的寫法調用該方法;

  • 匿名內部類方式:
public static <R> R typeConver(Function<String, R> function) {
    String str = "1235";
    R result = function.apply(str);
    return result;
}

@Test
public void testLambda4() {
    Integer result = typeConver(new Function<String, Integer>() {
        @Override
        public Integer apply(String s) {
            return Integer.valueOf(s);
        }
    });
    System.out.println(result);
}
  • Lambda方式:
public static <R> R typeConver(Function<String, R> function) {
    String str = "1235";
    R result = function.apply(str);
    return result;
}

@Test
public void testLambda4() {
    Integer result = typeConver((String s) -> {
        return Integer.valueOf(s);
    });
    System.out.println(result);
}

範例五:

IntConsumer是一個接口,先使用匿名內部類的寫法調用該方法;

  • 匿名內部類方式:
public static void foreachArr(IntConsumer consumer) {
    int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    for (int i : arr) {
        consumer.accept(i);
    }
}

@Test
public void testLambda5() {
    foreachArr(new IntConsumer() {
        @Override
        public void accept(int value) {
            System.out.println(value);
        }
    });
  • Lambda方式:
public static void foreachArr(IntConsumer consumer) {
    int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    for (int i : arr) {
        consumer.accept(i);
    }
}

@Test
public void testLambda5() {
    foreachArr((int value) -> {
        System.out.println(value);
    });
}

省略規則

  • 參數類型可以省略;
public static void foreachArr(IntConsumer consumer) {
    int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    for (int i : arr) {
        consumer.accept(i);
    }
}

@Test
public void testLambda5() {
    foreachArr((value) -> {
        System.out.println(value);
    });
}
  • 方法體只有一句代碼時大括號return和唯一一句代碼的分號可以省略;
public static void foreachArr(IntConsumer consumer) {
    int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    for (int i : arr) {
        consumer.accept(i);
    }
}

@Test
public void testLambda5() {
    foreachArr((value) -> System.out.println(value));
}
  • 方法只有一個參數時小括號可以省略;
public static void foreachArr(IntConsumer consumer) {
    int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    for (int i : arr) {
        consumer.accept(i);
    }
}

@Test
public void testLambda5() {
    foreachArr(value -> System.out.println(value));
}
  • 以上這些規則都記不住也可以省略不記,可通過idea的replaceLambda表達式快速生成lambda表達式;

Stream 流

Stream將要處理的元素集合看作一種流,在流的過程中,藉助Stream API對流中的元素進行操作。

Stream - 特性

Stream可以由數組或集合創建,對流的操作分爲兩種:

  • 中間操作,每次返回一個新的流,可以有多個;
  • 終端操作,每個流只能進行一次終端操作,終端操作結束後流無法再次使用。終端操作會產生一個新的集合或值。

Stream特性:

  • stream不存儲數據,而是按照特定的規則對數據進行計算,一般會輸出結果;

  • stream不會改變數據源,通常情況下會產生一個新的集合或一個值;

  • stream具有延遲執行特性,只有調用終端操作時,中間操作纔會執行。

image-20220321145135117

Stream - 創建方式

Stream創建方式有三種:

  • 通過 java.util.Collection.stream() 方法用集合創建流;

  • 使用java.util.Arrays.stream(T[] array)方法用數組創建流;

  • 使用Stream的靜態方法:of()、iterate()、generate()。

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * @author hos
 * @Createdate 2022/3/21 14:40
 */
public class StreamCreateType {

    public static void main(String[] args) {

        /**
         * Stream 流的創建有3種方式
         *  1. Collection.stream()方法用集合創建
         *  2. Arrays.stream(T[] array) 方法用數組創建
         *  3. 使用Stream的靜態方法:of()、iterate()、generate()
         */
        //方式一: Collection.stream()方法用集合創建
        List<String> list = Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9");
        // 創建一個順序流
        Stream<String> stream = list.stream();
        // 創建一個並行流
        Stream<String> stringStream = list.parallelStream();
        List<String> collect = stringStream.collect(Collectors.toList());

        //方式二: Arrays.stream(T[] array) 方法用數組創建
        int[] array = {1, 2, 3, 4, 5};
        IntStream stream1 = Arrays.stream(array);
        System.out.println(stream1.max().getAsInt());


        //方式三: 使用Stream的靜態方法:of()、iterate()、generate()
        Stream<Integer> intStream = Stream.of(1, 2, 3, 4, 5, 6);
        Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 3).limit(4);
        // 0 3 6 9
        stream2.forEach(System.out::println);

        AtomicInteger m = new AtomicInteger(10);
        Stream<Integer> stream3 = Stream.generate(()-> m.getAndIncrement()).limit(3);
        //10 11 12
        stream3.forEach(System.out::println);
    }
}

Stream - 使用

中間操作

map

map,可以將一個流的元素按照一定的映射規則映射到另一個流中;

map,接收一個函數作爲參數,該函數會被應用到每個元素上,並將其映射成一個新的元素。

filter

filter,對流中的元素進行條件過濾,符合過濾條件的才能繼續留在流中;

filter,按照一定的規則校驗流中的元素,將符合條件的元素提取到新的流中的操作。

distinct

distinct,去除流中的重複元素;

sorted

sorted(),自然排序,流中元素需實現Comparable接口;

sorted(Comparator com),Comparator排序器自定義排序。

limit

limit,可以設置流的最大長度,超出的部分將被拋棄;

skip

skip,跳過流中的前n個元素,返回剩下的元素;

flatMap

flatMap,接收一個函數作爲參數,將流中的每個值都換成另一個流,然後把所有流連接成一個流;

map只能把一個對象轉換成另一個對象來作爲流中的元素。而flatMap可以把一個對象轉換成多個對象作爲流中的元素。

終結操作

forEach

forEach方法,通過 lambda 表達式的方式遍歷集合中的元素;

forEach,對流中的元素進行遍歷操作,通過傳入的參數去指定對遍歷到的元素進行什麼具體操作。

count

count,用來獲取當前流中元素的個數;

max&min

max&min,可以用來或者流中的最值。

collect

collect,把當前流轉換成一個集合;

collect,把一個流收集起來,最終可以是收集成一個值也可以收集成一個新的集合;流不存儲數據,那麼在流中的數據完成處理後,需要將流中的數據重新歸集到新的集合裏。

reduce

reduce,把一個流縮減成一個值,能實現對集合求和、求乘積和求最值操作;

reduce,對流中的數據按照你指定的計算方式計算出一個結果。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章