JDK1.8常用的函數式接口@FunctionalInterface使用示例


JDK1.8常用的函數式接口@FunctionalInterface使用示例


從我們自定義的IHello示例來看,Lambda表達式其實是一種接口類型的數據類型,嚴格的說Lambda表達式的數據類型是:函數式接口,是一種特殊的接口,該接口使用@FunctionalInterface註解來標記(不是必須的,可以不用該註解標記,IHello接口就沒有使用該註解標記, ),並且接口中只能有一個抽象方法,可以有多個靜態方法或者默認方法, 每一個該類型的lambda表達式都會被匹配到這個抽象方法。

<code>@FunctionalInterface
public interface Comparator {
int compare(T o1, T o2);
// 其它static、default方法
}
/<code>

@FunctionalInterface: 該註解沒啥太大含義,該註解是給編譯器做檢查使用的,如果使用了該註解,編譯器就會檢查該接口中的抽象方法是不是隻有一個,如果有多個就會報錯:在接口Xxx中找到多個非覆蓋抽象方法

<code>@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}
/<code>

我們完善一下我們的IHello, 使用@FunctionalInterface註解

<code>@FunctionalInterface
public interface IHello {
void sayHello(String name);
}
/<code>

我們可以將lambda表達式當作任意只包含一個抽象方法的接口類型,也就是說我們的IHello接口無論叫什麼名字,接口中的方法無論叫什麼名字都無所謂(只是可讀性更好些),因此可以再進行抽象化一下,JDK1.8中提供了這樣的函數式接口,我們也不需要再定義IHello接口了,JDK1.8中提供了Supplier、Consumer、Function、BiFunction,這幾個是比較常用的

Supplier< T > 供應商:沒有參數,有返回值

<code>@FunctionalInterface
public interface Supplier {
T get();
}
/<code>

Consumer< T > 消費者: 只有一個參數,沒有返回值

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

Function< T, R > 函數:一個參數,一個返回值

<code>@FunctionalInterface
public interface Function {

R apply(T t);
}
/<code>

BiFunction< T, U, R > 二元函數:兩個參數,一個返回值

<code>@FunctionalInterface
public interface BiFunction {
R apply(T t, U u);
}
/<code>

Comparator< T > 比較器:接收兩個參數,返回比較的結果

<code>@FunctionalInterface
public interface Comparator {
int compare(T o1, T o2);
}
/<code>

使用以上四大函數式接口來取代自定義的接口IHello

<code>public class Main {
private static String end = ".";

public static void main(String[] args) {
// 直接使用JDK1.8提供的接口,不需要再定義IHello接口, 直接使用JDK提供的接口來接收Lambda表達式
Supplier<string> supplier = () -> "mengday: happy new year everyone!";
String result = supplier.get();
System.out.println(result);

Consumer<string> consumer = (name) -> System.out.println(name + ": " + "happy new year everyone!");
consumer.accept("mengday");

Function<string> func = (name) -> name + ": " + "happy new year everyone!";
String hi = func.apply("mengday");
System.out.println(hi);



// 在代碼塊的內部可以訪問靜態全局變量
// 在代碼塊中可以訪問外邊局部變量
// 在代碼塊的內部可以修改全局靜態變量
// 在代碼塊內部是不能訪問接口中的其它方法的
String split = ": ";
BiFunction<string> biFunction = (String name, String msg) -> {
end = "!";
String hello = name + split + msg + end;
return hello;
};
String hello = biFunction.apply("mengday", "happy new year everyone");
System.out.println(hello);

// 根據字符串長度比較大小
Comparator<string> comparator = (s1, s2) -> s1.length() - s2.length();
int compare = comparator.compare("abc", "ab");
System.out.println(compare);
}
}
/<string>/<string>/<string>/<string>/<string>/<code>

Predicate< T > 斷言 謂詞: 用於測試一個條件的真假

<code>package java.util.function;
import java.util.Objects;

@FunctionalInterface
public interface Predicate {
// 在給定的參數上評估這個謂詞
boolean test(T t);

// 返回一個組合的謂詞,表示該謂詞與另一個謂詞的短路邏輯AND
default Predicate and(Predicate super T> other) {

Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}

// 返回表示此謂詞的邏輯否定的謂詞,相當於not
default Predicate negate() {
return (t) -> !test(t);
}

// 返回一個組合的謂詞,表示該謂詞與另一個謂詞的短路邏輯或
default Predicate or(Predicate super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}

// 返回根據 Objects.equals(Object, Object)測試兩個參數是否相等的謂詞
static Predicate isEqual(Object targetRef) {
return (null == targetRef) ? Objects::isNull : object -> targetRef.equals(object);
}
}
/<code>

Main

<code>public static void main(String[] args) {
// 可以構造複雜的條件: 並且and、或者or、否negate
String email = "[email protected]";
Predicate<string> predicate = (str) -> str.length() > 20;

// 測試 emial.length > 0 的boolean
boolean result = predicate.test(email); // false

// 測試 !(emial.length > 0) 的boolean
result = predicate.negate().test(email); // true

Predicate<string> orPredicate = (str) -> str.contains("@");
// 測試 emial.length > 0 or emial.contains("@")
result = predicate.or(orPredicate).test(email); // true
}/<string>/<string>/<code>


分享到:


相關文章: