Java Lambda表達式

前言

隨着函數式編程的流程,Java8中也引入了函數式編程風格(Lambda表達式)。Lambda表達式允許我們將行爲傳遞到函數中,其可以替換匿名內部類實現的繁瑣的代碼。下面就是一個最經典的例子,用普通的匿名內部類一共用了6行代碼,使用Lambda表達式只需要1行代碼即可。也就是說,Lambda表達式在經常使用內部類情況下,可以大大的減少代碼量,還有就是Lambda表達式經常和Stream API一起使用。

// 匿名內部類
Runnable runnable1 = new Runnable() {
    @Override
    public void run() {
        System.out.println("do something");
    }
};
// Lambda表達式
Runnable runnable2 = () -> System.out.println("do something");

Lambda表達式使用

Lambda表達式格式

(Type1 param1, Type2 param2, ..., TypeN typeN) -> {
    statment1;
    statment2;
    // ......
    return statmentM;
}

操作符'->':Lambda操作符,該箭頭將Lambda表達式拆分爲左右兩部分

左側:參數列表,只有一個參數時可以不寫()

右側:Lambda表達式體,就抽象方法實現區域。只有一行代碼時可以不寫{},參數類型也可以不用寫(Java會通過上下文進行判斷)

上面是標準的Lambda表達式,一般情況下Lambda表達式可以分爲以下幾種類型:

無參數無返回值

() -> {
    statment1;
    statment2;
    ...
    statmentN;
}

有參數無返回值

(Type1 param1, Type2 param2, ..., TypeN paramN) -> {
    statment1;
    statment2;
    ...
    statmentN;
}

有參數有返回值

(Type1 param1, Type2 param2, ..., TypeN paramN) -> {
    statment1;
    statment2;
    ...
    statmentN;
    return value;
}

下面是一個實現List排序功能(根據字符串長度)的例子,可以看到這個例子是有參有返回值的,但是沒有寫return值(在單見場景下可以省略不寫)

List<String> list = new ArrayList<>();
list.add("my");
list.add("name");
list.add("is");
list.add("super");
list.add("man");
// 非lambda實現排序
Collections.sort(list, new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
        return o1.length() - o2.length();
    }
});
list.stream().forEach((x)->System.out.println(x));

// lambda實現排序
Collections.sort(list, (o1, o2) -> o2.length() - o1.length());
list.stream().forEach((x)->System.out.println(x));

函數式接口

定義與Lambda關係

函數式接口就是一個有且僅有一個抽象方法,但是有多個非抽象方法的接口。Lambda表達式需要函數式接口的支持,下面是自定義的函數式接口:

@FunctionalInterface
public interface TestService {
    void test();
}

// 使用代碼
TestService testService = ()->System.out.println("test");
testService.test();

@FunctionalInterface註解用於標識該接口是函數式接口,如果不滿足函數式接口規則,則編譯會報錯,當然函數式接口並不一定需要@FunctionalInterface註解。

Java中四種函數式接口

Java中常用的四個核心函數式接口包括:1、Consumer<T> 消費型接口;2、Supplier<T> 供給型接口;3、Function<R, T> 函數型接口;4、Predicate<T> 斷言型接口

消費型接口(Consumer<T>)

@FunctionalInterface
public interface Consumer<T> {
    
    void accept(T t);

    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

主要方法:
accept(T t):接受一個指定類型的參數,但無返回值

andThen(Consumer<? super T> after):從左向右執行

List<String> list2 = Arrays.asList("a","bb","ccc","dddd","eeeee");
Consumer<String> consumer = (x) -> System.out.println("input:" + x);
list2.stream().forEach(consumer);

供給型接口(Supplier<T>)

@FunctionalInterface
public interface Supplier<T> {

    T get();

}

主要方法:

T get():不接受任何參數,但返回執行類型的值

List<Integer> list1 = new ArrayList<>();
Supplier<Integer> supplier = () -> (int)(Math.random() * 100);
for (Integer i = 0; i < 10; i++) {
    list1.add(supplier.get());
}
list1.stream().forEach((x) -> System.out.println(x));

函數型接口(Function<R, T>)

@FunctionalInterface
public interface Function<T, R> {

    R apply(T t);

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

主要方法:

R apply(T t):接受一個指定類型的參數,返回一個執行的結果類型

andThen和compose方法:執行順序不一樣,andThen是從左向右執行;compose是從右向左執行;

Function<String, String> function1 = (x) -> x.toUpperCase();
List<String> list4 = list2.stream().map(function1).collect(Collectors.toList());
for (String elem : list4) {
    System.out.println("String Upper:" + elem);
}

Function<Integer, Integer> function2 = (x) -> x * 3;
Function<Integer, Integer> function3 = (x) -> x + 8;

System.out.println("andThen:" + function2.andThen(function3).apply(1));
System.out.println("compose:" + function2.compose(function3).compose(function3).apply(1));

斷言型接口(Predicate<T>)

@FunctionalInterface
public interface Predicate<T> {

    boolean test(T t);

    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

    default Predicate<T> negate() {
        return (t) -> !test(t);
    }

    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}

主要方法:

boolean test(T t):傳入指定值用於判斷,返回true或者false

and、negate、or、isEqual方法代表與、非、或、相等。

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