函式式介面詳解
函式式介面
以前一直好奇java能不能傳參的時候引數為方法,現在通過函式式介面可以做到了。以前一直用的不多,最近用到了就做一個簡單的彙總以及演示demo。
1.什麼是函式式介面?
- 只包含一個抽象方法的介面,稱為函式式介面
- 你可以通過Lambda表示式來建立該介面的物件。(若Lambda表示式丟擲一個受檢異常,那麼該異常需要在目標介面的抽象方法上進行宣告)
- 我們可以在任意函式式介面上使用@FunctionalInterface註解,這樣做可以檢查它是否是一個函式式介面,同時javadoc也會包含一條宣告,說明這個介面是一個函式式介面
2.自定義函式
package function; /** * @Description todo * @Author cz * @Date 2022/3/4 */ public class Function { @FunctionalInterface public interface Func<T> { T get(); } public static class FuncImpl implements Func<Integer> { @Override public Integer get() { return 3; } } public static Integer getInteger(Func<Integer> func) { return func.get(); } public static void testFunc(){ //匿名內部類的方式 System.out.println(getInteger(new Func<Integer>() { @Override public Integer get() { return 3; } })); //Lambda形式 System.out.println(getInteger(() -> 3)); //實現類的方式 System.out.println(getInteger(new FuncImpl())); } public static void main(String[] args) { //測試Function testFunc(); } }
3.JAVA內建四大核心函式式介面
在學習lambda表示式的時候,我們知道,要使用lambda表示式,我們就要建立一個函式式介面,那每次用lambda表示式的時候豈不是很麻煩,這時候,java給我們內建了四大核心函式式介面。
函式式介面 | 引數型別 | 返回型別 | 用途 |
---|---|---|---|
Consumer |
T | 無 | 對型別為T的物件應用操作,包含方法:void accept(T t) |
Supplier |
無 | 無 | 返回型別為T的物件,包含方法:T get() |
Function<T, R> 函式型介面 | T | R | 對型別為T的物件應用操作,並返回結果,結果是R型別的物件,包含方法:R apply(T t) |
Predicate |
T | 無 | 確定型別為T的物件是否滿足某約束,並返回boolean值。包含方法boolean test(T t) |
還有一些其他介面可看參照裡面的官方jdk文件裡面,或是直接看 java.util.function 包下面的介面
4.四大介面示例
4.1 Consumer:消費型介面
@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); }; } }
void accept(T t)
public static class ConsumerAcceptImpl implements Consumer<String> {
@Override
public void accept(String s) {
System.out.println(s);
}
}
public static void testConsumerAccept(String name, Consumer<String> consumer){
//do something with name
//then consumer the name
String helloName = String.format("hello %s", name);
consumer.accept(helloName);
}
public static void testAcceptMain(){
//lambda表示式
testConsumerAccept("張三", System.out::println);
//Consumer的實現類
testConsumerAccept("張三", new ConsumerAcceptImpl());
//匿名內部類
testConsumerAccept("張三", new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
}
Consumer
public static void testConsumerAndThen() {
Consumer<Student> c1 = (Student s) -> System.out.printf("%s:%s%n","c1", s.getSchool());
Consumer<Person> c2 = (Person p) -> System.out.printf("%s:%s%n", "c2", p.getName());
Consumer<Student> c3 = c1.andThen(c2);
Student s = new Student("s1的school", new Person("p", 11));
s.setName("student父類person的屬性name");
c3.accept(s);
}
/* 執行結果
c1:s1的school
c2:student父類person的屬性name
返回一個 consumer 的accept 為 先執行c1的accept然後執行c2的accept
*/
4.2 Supplier:共給型介面
@FunctionalInterface
public interface Supplier<T> {
T get();
}
T get( )
//需求:產生指定個數的整數,並放入集合中
public static List<Integer> getNumList(int num, Supplier<Integer> sup){
List<Integer> list = new ArrayList<>();
for(int i=0;i<num;i++) {
Integer n = sup.get();
list.add(n);
}
return list;
}
public static void testSupplierGet() {
List<Integer> numList = getNumList(10, ()->(int)(Math.random()*100 ));
for (Integer integer : numList) {
System.out.println(integer);
}
}
4.3 Function<T,R>:函式型介面
@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)
//需求:用於處理字串
public static String strHandler(String str, Function<String,String> fun) {
System.out.println("這裡先處理,然後交給fun處理,這裡的處理算是strHandler處理的。");
return fun.apply(str);
}
/*
對型別為T的物件應用操作返回型別為R的物件
*/
public static void testFunctionApply() {
String trimStr=strHandler("\t\t你好,world ",(str) -> {
System.out.println("這裡算是fun處理的,需要返回值");
return str.trim();
});
System.out.println(trimStr);
}
Function<T,V> compose(Function<? super V, ? extends T> before)
public static void testFunctionCompose(){
Function<String, String> before = String::trim; //對入參的String進行trim操作,返回trim以後的String;
Function<String, String> f2 = str -> str.replace("hello", "你好"); //對入參的String裡面的hello替換為你好
String rt = f2.compose(before).apply("hello, world ");
System.out.println(rt);
/* 此處compose的作用其實就是將多個Function的apply方法連線在一起用,compose裡面的將Function的apply方法將提前於它的呼叫的那個
Function的apply方法。看成是過濾器會很好理解。
上述執行過程是 compose返回的Function f3.apply(f2.apply(before.apply(str)))
*/
}
Function<T, V> andThen(Function<? super R, ? extends V> after)
public static void testFunctionAndThen(){
Function<String, String> after = String::trim; //對入參的String進行trim操作,返回trim以後的String;
Function<String, String> f2 = str -> str.replace("hello", "你好"); //對入參的String裡面的hello替換為你好
String rt = f2.andThen(after).apply("hello, world ");
System.out.println(rt);
/* 此處compose的作用其實就是將多個Function的apply方法連線在一起用,andThen裡面的將Function的apply方法將後於它的呼叫的那個
Function的apply方法。看成是過濾器會很好理解。
上述執行過程是 andThen返回的Function f3.apply(after.apply(f2.apply(str)))
*/
}
Function<T, T> identity()
/* 測試 Function<T, T> identity() 用法
identity()返回的是一個入參和出參相同的Function*/
public static void printString(String str, Function<String, String> f1){
System.out.println(f1.apply(str));
}
public static void testFunctionIdentity(){
printString("s1", Function.identity());
}
4.4 Predicate:斷言型介面
@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);
}
@SuppressWarnings("unchecked")
static <T> Predicate<T> not(Predicate<? super T> target) {
Objects.requireNonNull(target);
return (Predicate<T>)target.negate();
}
}
boolean test(T t) 用來處理引數T,看是否滿足要求,可以理解為 條件A
public static void testPredicateTest(){
Predicate<Integer> predicateTest = x -> x > 0;
System.out.println(predicateTest.test(10));
}
//true
Predicate
public static void testPredicateAnd(){
Predicate<Integer> predicate = x -> x > 0;
Predicate<Integer> other = x -> x < 10;
System.out.println(predicate.and(other).test(11));
}
//flase
Predicate
public static void testPredicateNegate(){
Predicate<Integer> predicate = x -> x > 0;
System.out.println(predicate.negate().test(10));
}
//false
Predicate
public static void testPredicateOr(){
Predicate<Integer> predicate = x -> x > 0;
Predicate<Integer> other = x -> x < 0;
predicate.or(other).test(0);
}
//false
Predicate
public static void testPredicateIsEqual(){
Object obj = new Object();
Predicate.isEqual(obj).test(obj);
}
//true
Predicate
public static void testPredicateNot(){
Predicate<Integer> p1 = x -> x>0;
System.out.println(Predicate.not(p1).test(-1));
}
//true
5. 其他與Predicate相關的介面
-
BiPredicate<T, U>
針對兩個引數,看兩個引數是否符合某個條件表示式
-
DoublePredicate
看一個double型別的值是否符合某個條件表示式
-
IntPredicate
看一個int型別的值是否符合某個條件表示式
-
LongPredicate
看一個long型別的值是否符合某個條件表示式
參考:
1.https://www.jianshu.com/p/8005f32caf3d
2.https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/function/package-summary.html
3.https://www.jianshu.com/p/b38ff80e3039
4.原始碼地址:https://gitee.com/ashscc/java-ptn/tree/master/baseJDK/src/main/java/function
本文來自部落格園,作者:orangeScc,轉載請註明原文連結:https://www.cnblogs.com/ashScc/p/15972683.html