JDK中有許多函數(shù)式接口,也會(huì)有許多方法會(huì)使用函數(shù)式接口作為參數(shù),同時(shí)在各種源碼中也大量使用了這些方法,那么我們?cè)趯?shí)際工作中應(yīng)該如何使用!我們就來(lái)盤(pán)一盤(pán),這樣也有助于寫(xiě)出優(yōu)雅的代碼,使我們?cè)陂喿x源碼時(shí)事半功倍。
1 JDK中常見(jiàn)的Lamada表達(dá)式
Java中可以使用Lamada表達(dá)式的接口都有@FunctionalInterface注解。
先來(lái)看看util.function包下面含有FunctionalInterface注解的接口。一屏顯示不全,可見(jiàn)功能非常齊全。
鑒于常用的一些函數(shù)式接口有Function/Consumer/Supplier/Predicate以及Runnable等。本篇介紹這幾類(lèi)接口。
1.1 Runnable
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
Runnable 使用Lamada方式書(shū)寫(xiě)時(shí),無(wú)參數(shù),無(wú)返回值。最終執(zhí)行的是run方法
使用Demo
new Thread(() - > {
System.out.println("JavaNorth Runnable");
}).start();
1.2 Function
Function 表示接受一個(gè)參數(shù)并產(chǎn)生結(jié)果的函數(shù)。
@FunctionalInterface
public interface Function< T, R > {
/**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
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;
}
}
Function接受一個(gè)參數(shù)T,并且有返回值 R, 其實(shí)現(xiàn)也主要是實(shí)現(xiàn)此方法 R apply(T t);
Function 的一個(gè)示例:
List< String > list = new ArrayList< String >();
List< String > collect = list.stream().map((x) - > {
return "Java North Function" + x;
}).collect(Collectors.toList());
上述示例中是一個(gè)stream的map方法。其中x為輸入?yún)?shù),『"Java North and" + x』為輸出。
1.3 Consumer
Consumer表示接受一個(gè)參數(shù),沒(méi)有返回值的操作,主要方法為 void accept(T t);
@FunctionalInterface
public interface Consumer< T > {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
default Consumer< T > andThen(Consumer< ? super T > after) {
Objects.requireNonNull(after);
return (T t) - > { accept(t); after.accept(t); };
}
}
1.3.1 Consumer 在Java中的應(yīng)用
常見(jiàn)的有List的forEach等。
list.forEach(x - > System.out.println( "Java North Consumer test " + x));
x為參數(shù),輸出語(yǔ)句直接執(zhí)行。
下面的map的forEach參數(shù)為BiConsumer,其入?yún)⒂袃蓚€(gè)。
Map String,String > map = new HashMap >();
map.forEach((K,V) - > {
System.out.println("Java North Big Consumer MAP key : " +K + " value: "+V );
});
1.3.2 自定義帶有Consumer的方法
public class ConsumerBiConsumerDemo {
public static void main(String[] args) {
Consumer< String > conString = (x) - > System.out.println(x.toUpperCase());
conString.accept("i love java north ");
BiConsumer< String, String > biCon = (x,y) - > System.out.println (x + y);
biCon.accept("i love ","java");
List< Person > plist = Arrays.asList(new Person("Java"),new Person("North"));
acceptAllEmployee(plist,p - > System.out.println(p.name));
acceptAllEmployee(plist,person - > {person.name = "unknow";});
acceptAllEmployee(plist,person - > System.out.println(person.name));
}
public static void acceptAllEmployee(List< Person > plist, Consumer< Person > con){
plist.forEach(person - > {con.accept(person);});
}
}
class Person{
public String name;
public Person (String name){
this.name = name;
}
}
1.4 Supplier
Supplier沒(méi)有參數(shù),有一個(gè)返回值。
@FunctionalInterface
public interface Supplier< T > {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
Supplier 示例如下:
public class SupplierDemo {
public static void main(String[] args) {
SupplierDemo sdemo = new SupplierDemo();
Supplier< LocalDateTime > s = () - > LocalDateTime.now();
LocalDateTime localDateTime = s.get();
System.out.println(s.get());
Supplier< List > listSupplier = sdemo.listSupplier();
List list = listSupplier.get();
Person person = personFactory(Person::new);
System.out.println(person);
Person javaNorth = personFactory(() - > new Person("JavaNorth"));
System.out.println(javaNorth);
}
public Supplier< List > listSupplier(){
return ArrayList::new;
}
public static Person personFactory(Supplier< ? extends Person > s){
Person person = s.get();
if(person.getName() == null) person.setName("default");
person.setAge(18);
return person;
}
static class Person {
String name;
int age;
public Person() { }
public Person(String name) {
this.name = name;
}
。。。
}
}
1.5 Predicate
主要方法為test,其主要是傳入一個(gè)參數(shù),返回一個(gè)boolean類(lèi)型的值。
@FunctionalInterface
public interface Predicate< 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}
*/
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);
}
......
}
Predicate簡(jiǎn)單示例:
public class PredicateDemo {
public static void main(String[] args) {
Predicate< Integer > predicate = (s) - > s > 5;
Predicate< Integer > predicate2 = (s) - > s > 8;
System.out.println(" 3 大于5 ? " + predicate.test(3));
System.out.println(" 6 大于5 ? " + predicate.test(6));
System.out.println("7 大于5 and 大于8 " + predicate.and(predicate2).test(7));
System.out.println("7 大于5 or 大于8 " + predicate.or(predicate2).test(7));
List< Integer > list = Arrays.asList(3,5,6,2,8,4,7,9);
List< Integer > collect = list.stream().filter(predicate).collect(Collectors.toList());
System.out.println(list);
System.out.println(collect);
}
}
上述代碼運(yùn)行結(jié)果
3 大于5 ? false
6 大于5 ? true
7 大于5 and 大于8 false
7 大于5 or 大于8 true
[3, 5, 6, 2, 8, 4, 7, 9]
[6, 8, 7, 9]
2 常用的Lamada參數(shù)特征
Lamada 的一些表達(dá)式將方法的一些執(zhí)行邏輯放到了參數(shù)中,使得方法的返回值根據(jù)傳入的參數(shù)的邏輯而變化。從而實(shí)現(xiàn)了在一定的方法不變的情況下,使代碼執(zhí)行傳入?yún)?shù)相關(guān)的邏輯。
常用的一些Lamada使用如下:
Runnable 無(wú)入?yún)ⅲ瑹o(wú)返回值 。
() - > { System.out.println(strF.apply("javaNorth Runnable"));}
Function 有入?yún)?,有返回?/strong>
Function strF = (s) - > { return s + "javaNorth Function"; };
System.out.println(strF.apply("TEST "));
Consumer有入?yún)?,無(wú)返回值。
Consumer< String > srtC = (s) - > {System.out.println(s + "javaNorth TEST ");};
srtC.accept("Hello World");
Supplier 無(wú)入?yún)?,有返回值?/strong>
Supplier< String > srtP = () - > {return "I love avaNorth ";};
System.out.println(srtP.get());
Predicate 有入?yún)ⅲ祷匾粋€(gè)boolean類(lèi)型的值
Predicate< Integer > predicate = (s) - > s > 5;
System.out.println(" 3 大于5 ? " + predicate.test(3));
3 自定義Lamada函數(shù)式接口
結(jié)合之前的常用Lamada函數(shù)的介紹,下面我們自定義一個(gè)簡(jiǎn)單的函數(shù)式接口。
@FunctionalInterface
public interface MyFunction< T > {
public void print(T t);
}
public class MyFunctionDemo {
public static void printString(String str , MyFunction< String > myF){
myF.print(str);
}
public static void main(String[] args) {
printString("I love " , (str) - > {System.out.println(str + "Java North");});
}
}
其實(shí)很簡(jiǎn)單,就是展示了一下自定義函數(shù)式接口的應(yīng)用實(shí)例而已。
總結(jié)
函數(shù)式接口的使用可以簡(jiǎn)化我們的代碼,很大程度上提高代碼的可讀性。在程序執(zhí)行上可能性能稍微有所降低,但對(duì)開(kāi)發(fā)帶來(lái)的便捷與好處是大于其性能上的微弱損失的。除了介紹的幾種常見(jiàn)的函數(shù)式編程以外,還有許多其他的函數(shù)式接口等著我們?nèi)ダ谩B?tīng)完這些話之后,軟軟猿妹也對(duì)常用的函數(shù)式接口有所了解,接下來(lái)下定決心要好好學(xué)一學(xué)函數(shù)式接口了。
-
接口
+關(guān)注
關(guān)注
33文章
8885瀏覽量
152976 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4365瀏覽量
63855 -
JDK
+關(guān)注
關(guān)注
0文章
82瀏覽量
16775
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
什么是正則表達(dá)式?正則表達(dá)式如何工作?哪些語(yǔ)法規(guī)則適用正則表達(dá)式?

如何創(chuàng)建正則的表達(dá)式?
防范表達(dá)式的失控
深入淺出boost正則表達(dá)式
Python正則表達(dá)式的學(xué)習(xí)指南

Python正則表達(dá)式指南

Oracle中常用的函數(shù)與表達(dá)式講解

Lambda表達(dá)式詳解
表達(dá)式與邏輯門(mén)之間的關(guān)系

C語(yǔ)言的表達(dá)式

shell腳本基礎(chǔ):正則表達(dá)式grep

一文詳解Verilog表達(dá)式

評(píng)論