Java8 由Oracle在2014年發(fā)布吨拍,是繼Java5之后最具革命性的版本斧抱。
Java8吸收其他語言的精髓帶來了函數(shù)式編程,lambda表達式脂倦,Stream流等一系列新特性畅厢,學(xué)會了這些新特性冯痢,可以讓你實現(xiàn)高效編碼優(yōu)雅編碼。
函數(shù)式接口是指只定義了一個抽象方法的接口,不包括default默認方法系羞。
函數(shù)式接口的抽象方法的簽名稱為函數(shù)描述符郭计,通過函數(shù)描述符可以很好得到Lambda表達式的簽名。
常見的函數(shù)式接口有:Runnable, Callable, Comparator等椒振。除此之外昭伸,Java8設(shè)計者還新增了一些比較抽象的函數(shù)式接口,比如:Predicate, Consumer, Supplier, Function, UnaryOperator, BinaryOperator等, 這些函數(shù)式接口定義在java.util.function包中澎迎。
接下來詳細介紹function包中定義的抽象接口:
Predicate是謂詞的意思庐杨,用來判斷泛型T對象是否符合條件,如果符合返回true夹供,否則返回false灵份。
查看jdk源碼,定義了一個抽象方法test:
@FunctionalInterfacepublicinterfacePredicate<T>{/**
? ? * Evaluates this predicate on the given argument.
? ? *
? ? * @param t the input argument
? ? * @return {@code true} if the input argument matches the predicate,
? ? * otherwise {@code false}
? ? */booleantest(T t);}
Predicate是一個接口所以不能直接實例化哮洽,可以使用匿名類或者Lambda表達式實例化填渠。以Lambda為例:
// 接收string對象,判斷是否為空鸟辅,返回booleanPredicate predicate=(String str)->str.isEmpty();
下面以一個校驗參數(shù)的實例說明:
@TestpublicvoidtestPredicate(){String input="hello java8";if(validate(input,(str)->!str.isEmpty()&&str.length()>5)){// 校驗輸入System.out.println("valid input");}}// 第二個參數(shù)接收一個Predicate實例private<T>booleanvalidate(T input,Predicate<T>predicate){returnpredicate.test(input);}
Predicate: T -> boolean
接受泛型T對象返回boolean氛什。
注意:java.util.function包中還針對基本類型封裝了類似IntPredicate, LongPredicate等接口,這無非是表明只接受Int或Long類型的輸入匪凉,后面Consumer等函數(shù)式接口與這個類似枪眉,本文不再贅述。
Consumer是消費者的意思再层,用來接收一個泛型T對象贸铜,執(zhí)行相關(guān)操作,最后返回void聂受。
查看jdk源碼蒿秦,定義了一個抽象方法accept:
@FunctionalInterfacepublicinterfaceConsumer<T>{/**
? ? * Performs this operation on the given argument.
? ? *
? ? * @param t the input argument
? ? */voidaccept(T t);}
使用Lambda表達式實例化Consumer接口:
Consumer<String>consumer=(str)->System.out.println(str);
下面以打印字符串的實例講解Consumer的用法:
@TestpublicvoidtestConsumer(){String input="hello java8";// 打印輸入consume(input,(str)->System.out.println(str));}private<T>voidconsume(T input,Consumer<T>consumer){consumer.accept(input);}
Consumer: T -> void
接受泛型T對象返回void。
Supplier是提供者的意思饺饭,用來生成泛型T對象渤早。
查看jdk源碼职车,定義了一個抽象方法get:
@FunctionalInterfacepublicinterfaceSupplier<T>{/**
? ? * Gets a result.
? ? *
? ? * @return a result
? ? */Tget();}
使用Lambda表達式實例化Supplier接口:
Supplier supplier=()->"Hello Java8 supplier";
下面以獲取當(dāng)前時間的實例講解Supplier的用法:
@TestpublicvoidtestSupplier(){// 獲取當(dāng)前時間Long currentTime=supply(()->System.currentTimeMillis());}private<T>Tsupply(Supplier<T>supplier){returnsupplier.get();}
Supplier: void -> T
接受void返回泛型T對象瘫俊。
Function是函數(shù)的意思,用來定義一個抽象函數(shù)悴灵,接收泛型T對象扛芽,返回泛型R對象。
查看jdk源碼积瞒,定義了一個抽象方法apply:
@FunctionalInterfacepublicinterfaceFunction<T,R>{/**
? ? * Applies this function to the given argument.
? ? *
? ? * @param t the function argument
? ? * @return the function result
? ? */Rapply(T t);}
使用Lambda表達式實例化Function接口:
Function<String,Integer>function=(str)->str.length();
下面以判斷輸入是否以指定字符串開頭的實例講解Function的用法:
@TestpublicvoidtestFunction(){String input="hello java8";if(func(input,(String str)->str.startsWith("hello"))){System.out.println("start with hello");}}private<T,R>Rfunc(T t,Function<T,R>function){returnfunction.apply(t);}
Function: T -> R
接受泛型T對象川尖,返回泛型R對象。
UnaryOperator是一元操作符的意思茫孔,接收一個泛型T對象參數(shù)叮喳,返回相同T類型對象被芳。
查看jdk源碼,UnaryOperator繼承自Function接口馍悟,定義了一個identity方法:
@FunctionalInterfacepublicinterfaceUnaryOperator<T>extendsFunction<T,T>{/**
? ? * Returns a unary operator that always returns its input argument.
? ? *
? ? * @param <T> the type of the input and output of the operator
? ? * @return a unary operator that always returns its input argument
? ? */static<T>UnaryOperator<T>identity(){returnt->t;}}
使用Lambda表達式實例化UnaryOperator接口:
UnaryOperator<Integer>unaryOperator=(Integer i)->i*i;
下面以整數(shù)遞增的實例講解UnaryOperator的用法:
@TestpublicvoidtestUnaryOperator(){UnaryOperator<Integer>unaryOperator=(Integer i)->i*i;intinput=0;intresult=unaryOperate(input,(Integer i)->i+1);// output: 1System.out.println(result);}private<T>TunaryOperate(T t,UnaryOperator<T>unaryOperator){returnunaryOperator.apply(t);}
UnaryOperator: T -> T
接受泛型T對象畔濒,返回泛型T對象。
BinaryOperator是二元操作符的意思锣咒,接收兩個相同泛型參數(shù)類型T侵状,返回R類型對象。
查看jdk源碼毅整,BinaryOperator繼承自BiFunction接口趣兄,繼承了BiFunction的apply方法:
@FunctionalInterfacepublicinterfaceBinaryOperator<T>extendsBiFunction<T,T,T>{/**
? ? * Applies this function to the given arguments.
? ? *
? ? * @param t the first function argument
? ? * @param u the second function argument
? ? * @return the function result
? ? */Rapply(T t,U u);}
使用Lambda表達式實例化BinaryOperator接口:
BinaryOperator<String>binaryOperator=(String str1,String str2)->str1+str2;
下面以整數(shù)求和實例講解BinaryOperator的用法:
@TestpublicvoidtestBinaryOperator(){inta1=10;inta2=20;intsum=binaryOperate(a1,a2,(Integer i1,Integer i2)->i1+i2);// output: 30System.out.println(sum);}private<T>TbinaryOperate(T t1,T t2,BinaryOperator<T>binaryOperator){returnbinaryOperator.apply(t1,t2);}
BinaryOperator: (T, T) -> T
接受兩個泛型T對象,返回一個泛型T對象悼嫉。
java.util.function包中定義了很多函數(shù)式抽象接口艇潭,只要記住它們的函數(shù)描述符就可以很方便的知道他們的使用方法。
Predicate: T -> boolean
Consumer: T -> void
Supplier: void -> T
Function: T -> R
UnaryOperator: T -> T
BinaryOperator: (T, T) -> T