麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學院 > 開發設計 > 正文

Java8vs.Scala之Lambda表達式

2019-11-14 14:56:30
字體:
來源:轉載
供稿:網友

Hussachai Puripunpinyo認為java是一門靜態的強類型語言,因此雖然在Java 8 中函數已經成了一等公民,可以作為函數的參數或者返回值來傳遞,但是它必須要有一個類型,那就是接口,而Lambda表達式就是實現了Functional接口的對象。雖然開發人員不需要為函數對象的創建而擔心,因為編譯器會做這些事情,但是Java并沒有Scala那么出色的類型推理機制,在Java中聲明Lambda表達式必須要指定目標類型。考慮到Java必須維持向后兼容性,這樣做也是可以讓人接受和理解的,事實上在兼容性方面Java已經做的足夠好了,例如Thread.stop()在JDK 1.0中就已經有了,雖然被標記為“已廢棄”數十年,但是現在依然存在,因而不應該因為其他語言有更好的語法就期望Java快速地改變自己的語法。

為了支持Lambda表達式Java引入了函數式接口,該接口只有一個抽象方法。@FunctionalInterface是一個注解,用來表明被注解的接口是一個函數式接口,該注解是可選的,只有需要對接口是否符合契約做檢查的時候才需要使用。

在Java中,Lambda表達式必須要有一個類型,而且類型必須有且僅有一個抽象方法,而大部分已有的回調接口已經滿足這一需求,因此用戶不需要對它們做出任何改變就能夠重用這些接口。例如:

//在Java 8之前Runnable r = new Runnable(){    public void run(){        System.out.PRintln(“This should be run in another thread”);    }};//Java 8Runnable r = () -> System.out.println(“This should be run in another thread”);

對于有一個參數并且有返回值的函數,Java 8提供了一組通用的函數式接口,這些接口在java.util.function包中,使用方式如下:

//Java 8Function<string, integer=""> parseInt = (String s) -> Integer.parseInt(s);

因為參數類型可以從Function對象的類型聲明中推斷出來,所以類型和小括號都可以省略:

//Java 8Function<string, integer=""> parseInt = s -> Integer.parseInt(s);

對于需要兩個參數的函數,Java 8提供了BiFunction:

//Java 8BiFunction<integer, integer="" integer,=""> multiplier =   (i1, i2) -> i1 * i2; //you can’t omit parenthesis here!

對于需要3個及以上參數的接口,Java 8并沒有提供相應的TriFunction、QuadFunction等定義,但是用戶可以定義自己的TriFunction,如下:

//Java 8@FunctionalInterfaceinterface TriFunction<a, r="" c,="" b,=""> {    public R apply(A a, B b, C c);}

在引入了之前定義好的接口之后就可以這樣聲明Lambda表達式:

//Java 8TriFunction<integer, integer="" integer,=""> sumOfThree   = (i1, i2, i3) -> i1 + i2 + i3;

對于語言的設計者為什么會止步于BiFunction,Hussachai Puripunpinyo認為TriFunction、QuadFunction等需要更多參數的接口需要太多的類型聲明,接口的定義變得非常長,同時又怎么決定定義到哪一個才最合適呢,總不能一直定義到包含9個參數和一個返回值類型的EnnFunction吧!

以上示例顯示參數越多,類型定義越冗長,甚至可能整整一行都是類型聲明,那么必須要聲明類型么?答案是在Java中必須如此,但是在Scala中就簡單的多了。

Scala也是一門靜態強類型的語言,但是它從誕生開始就是一門函數式語言,完美融合了面向對象范式和函數式語言范式。Scala中的Lambda表達式也有一個類型,但是語言的設計者采用了數字而不是拉丁語來命名,Scala為開發者提供了0到22個參數的接口定義(Function0、Function1、… Function22),如果需要更多的參數,那么或許是開發者在設計上就存在問題。在Scala中Function的類型是特性(trait),類似于Java中的抽象類。

Scala中的Runnable示例與Java中的實現方式不同:

//ScalaFuture(println{“This should be run in another thread”})//以上代碼等同于//Java 8//assume that you have instantiated ExecutorService beforehand.Runnable r = () -> System.out.println(“This should be run in another thread”);executorService.submit(r);

在Scala中聲明一個Lambda表達式不必像Java那樣必須顯式指定類型,而且方式也有很多:

//Java 8Function<string, integer=""> parseInt = s -> Integer.parseInt(s);//Scalaval parseInt = (s: String) => s.toInt//orval parseInt:String => Int = s => s.toInt//orval parseInt:Function1[String, Int] = s => s.toInt

如果需要更多的參數:

//Java 8PentFunction<integer, integer="" integer,=""> sumOfFive   = (i1, i2, i3, i4, i5) -> i1 + i2 + i3 + i4 + i5;//Scalaval sumOfFive = (i1: Int, i2: Int, i3: Int, i4: Int, i5: Int) =>   i1 + i2 + i3 + i4 + i5;

可以看到,Scala的語法更簡潔,可讀性更好,開發者不需要聲明接口類型,通過參數列表中的類型就能看出對象的類型。

//Java 8PentFunction<string, integer,="" string="" string,="" boolean,="" double,="">   sumOfFive = (i1, i2, i3, i4, i5) -> i1 + i2 + i3 + i4 + i5;//Scalaval sumOfFive = (i1: String, i2: Int, i3: Double, i4: Boolean, i5: String) => i1 + i2 + i3 + i4 + i5;

對于上面這段代碼,開發者一打眼就能看出i3是Double類型的,但是在Java 8中開發者必須要數一數才能看出來,如果要在Java 8中達到這種效果,那只有從格式上來做文章了:

//Java 8 PentFunction sumOfFive = (Integer i1, String i2, Integer i3, Double i4, Boolean i5) -> i1 + i2 + i3 + i4 + i5;

但是這真是非常糟糕,開發者必須一次次地鍵入類型,另外,Java 8并沒有定義PentFunction,你還必須自己定義:

//Java 8@FunctionalInterfaceinterface PentFunction<a, r="" c,="" b,="" e,="" d,=""> {    public R apply(A a, B b, C c, D d, E e);}

Hussachai Puripunpinyo認為Scala在函數式方面做的更好,一方面是因為Scala本身就是一門函數式語言,另一方面是因為Java語言的設計者在引入新東西的時候必須要考慮兼容性,因而有很多約束。但是即使如此,Java 8依然引入了一些非常酷的特性,例如方法引用,該特性就能夠讓Lambda表達式的聲明更加簡短:

//Java 8Function<string, integer=""> parseInt = s -> Integer.parseInt(s);//使用方法引用可以簡寫為://Java 8Function<string, integer=""> parseInt = Integer::parseInt;

在Java 8中,方法引用的構建規則有3種:

  1. (args) -> ClassName.staticMethod(args);
    可以重寫為ClassName::staticMethod;
    Function<integer, string=""> intToStr = String::valueOf;
  2. (instance, args) -> instance.instanceMethod(args);
    可以重寫為ClassName::instanceMethod;
    BiFunction<string, integer="" string,=""> indexOf = String::indexOf;
  3. (args) -> expression.instanceMethod(args);
    可以重寫為expression::instanceMethod;
    Function<string, integer=""> indexOf = new String()::indexOf;

流API就大量使用了這種語法來簡化代碼的編寫:

pets.stream().map(Pet::getName).collect(toList());// The signature of map() function can be derived as//  Stream map(Function mapper)

前兩天在一群里看見有人推薦一個app叫問啊,就可以發題答題那種的,感覺就跟uber滴滴打車似的,一般這種軟件一上來就砸錢給紅包啥的,哥之前刷過uber的單有經驗!試驗了幾次應該可以刷,把注冊紅包和之前領的紅包錢套現,目前我提了五十多,目測還能刷更多。ps,但是盡量要問技術相關的問題,不然容易被封。

  有技術的可以自己試,不會的可以q我QQ群290551701


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 亚洲二区不卡 | 国产91丝袜在线播放 | 久久久久久久久久久久久久久久久久 | www久久艹| 综合网日日天干夜夜久久 | 污视频在线免费播放 | 久久亚洲精品久久国产一区二区 | 毛片视频网站 | 中文字幕网在线 | 国产精品1区,2区,3区 | 性大片免费看 | 国产精品自在线拍 | 成人性视频免费网站下载软件 | 亚州综合一区 | a一级黄色毛片 | 免费一级欧美在线观看视频 | 国产小视频在线 | 红杏网站永久免费视频入口 | 国产一级aaa全黄毛片 | 一级大黄毛片免费观看 | 国产毛片毛片 | 久久成人午夜视频 | 国产乱一区二区三区视频 | 亚洲嫩草av | 私库av在线免费观看 | 精品国产视频一区二区三区 | 欧美一级黄色录相 | 性欧美在线视频 | 亚洲福利在线免费观看 | 一级外国毛片 | 色播视频在线播放 | 一区二区三区日韩电影 | 中文字幕一区二区三区四区 | 娇喘在线| 青久草视频 | 在线观看免费毛片视频 | 久久精品国产亚洲7777 | 国产高潮国产高潮久久久91 | 国产精品嘿咻嘿咻在线播放 | 日韩精品中文字幕一区 | 国产一国产精品一级毛片 |