java 8 部分新特性和函數式編程__PHP

來源:互聯網
上載者:User

1.介面可以添加非抽象的方法和靜態方法,使用關鍵字 default 即可
代碼如下:

public interface Defaulable {    void printName();    default void printAge(){        System.out.println(19);    }     static void printSex(){        System.out.println("女");    }}

實現如下:

public class DefaulableImpl implements Defaulable {    @Override    public void printName() {        System.out.println("abel");    }    public static void main(String [] args){        Defaulable d=new DefaulableImpl();          d.printName();          d.printAge();        Defaulable.printSex();    }}
Java1.8中介面和抽象類別存在的不同。

當兩個介面都定義兩個 完全相同的 預設方法
default void printAge(){
//do Something
},
實作類別同時實現這兩個介面,會出現衝突。 實作類別需要重新覆寫該預設方法() 。 抽象類別允許非靜態和非final的域,允許方法成為public,static和final 所有的介面方法本質為public的。

JDK 8 爭議性的把抽象類別的優點帶給介面。造成的影響是今天有大量的抽象類別通過預設方法可能被替換為介面。 2. :: 方法引用

方法引用提供了非常有用的文法,可以直接引用已有Java類或對象(執行個體)的方法或構造器。與lambda聯合使用,方法引用可以使語言的構造更緊湊簡潔,減少冗餘代碼。

::是java 8裡引入lambda後的一種用法,表示引用,

比如靜態方法的引用String::valueOf;比如構造器的引用,ArrayList::new比如輸出方法的引用 list.forEach(System.out::println);也可以引用類的屬性。

下面,我們以定義了4個方法的Car這個類作為例子,區分Java中支援的4種不同的方法引用。

public static class Car {    public static Car create( final Supplier< Car > supplier ) {        return supplier.get();    }                  public static void collide( final Car car ) {        System.out.println( "Collided " + car.toString() );    }    public void follow( final Car another ) {        System.out.println( "Following the " + another.toString() );    }    public void repair() {           System.out.println( "Repaired " + this.toString() );    }}

第一種方法引用是構造器引用,它的文法是Class::new,或者更一般的Class< T >::new。請注意構造器沒有參數。

final Car car = Car.create( Car::new ); //引用 Car 的 new 構造方法final List< Car > cars = Arrays.asList( car );

第二種方法引用是靜態方法引用,它的文法是Class::static_method。請注意這個方法接受一個Car類型的參數。

cars.forEach( Car::collide );

第三種方法引用是特定類的任意對象的方法引用,它的文法是Class::method。請注意,這個方法沒有參數。

cars.forEach( Car::repair );

最後,第四種方法引用是特定對象的方法引用,它的文法是instance::method。請注意,這個方法接受一個Car類型的參數

final Car police = Car.create( Car::new );cars.forEach( police::follow );

運行上面的Java程式在控制台上會有下面的輸出(Car的執行個體可能不一樣):

Collided com.javacodegeeks.java8.method.references.MethodReferences$Car@7a81197dRepaired com.javacodegeeks.java8.method.references.MethodReferences$Car@7a81197dFollowing the com.javacodegeeks.java8.method.references.MethodReferences$Car@7a81197d
3.Clock

Clock類提供了訪問當前日期和時間的方法,Clock是時區敏感的,可以用來取代 System.currentTimeMillis() 來擷取當前的微秒數。某一個特定的時間點也可以使用Instant類來表示,Instant類也可以用來建立老的java.util.Date對象。

 ZoneId zone1 = ZoneId.of("Europe/Berlin");         System.out.println(ZoneId.getAvailableZoneIds());         Clock clock=Clock.system(zone1);//       Clock clock=Clock.systemDefaultZone();//擷取預設時區         Instant instant=clock.instant();         long millis = clock.millis();         System.out.println(millis);//可替換System.currentTimeMillis()         System.out.println(clock+"-----sd"+instant);

如果你需要特定時區的日期/時間,那麼ZonedDateTime是你的選擇。它持有ISO-8601格式具具有時區資訊的日期與時間。下面是一些不同時區的例子:

 ZoneId zone1 = ZoneId.of("Europe/Berlin");         Clock clock=Clock.system(zone1);         final ZonedDateTime zonedDatetime = ZonedDateTime.now();         final ZonedDateTime zonedDatetimeFromClock = ZonedDateTime.now( clock );         final ZonedDateTime zonedDatetimeFromZone = ZonedDateTime.now( ZoneId.of( "America/Los_Angeles" ) );         System.out.println( zonedDatetime );         System.out.println( zonedDatetimeFromClock );         System.out.println( zonedDatetimeFromZone );

輸出結果

2016-09-11T16:45:08.711+08:00[Asia/Shanghai]2016-09-11T10:45:08.711+02:00[Europe/Berlin]2016-09-11T01:45:08.724-07:00[America/Los_Angeles]
4. Base64

在Java 8中,Base64編碼成為了Java類庫的標準。Base64類同時還提供了對URL、MIME友好的編碼器與解碼器。

除了這十大新特性之外,還有另外的一些新特性:

更好的類型推測機制:Java 8在類型推測方面有了很大的提高,這就使代碼更整潔,不需要太多的強制類型轉換了。

編譯器最佳化:Java 8將方法的參數名加入了位元組碼中,這樣在運行時通過反射就能擷取到參數名,只需要在編譯時間使用-parameters參數。

並行(parallel)數組:支援對數組進行平行處理,主要是parallelSort()方法,它可以在多核機器上極大提高數組排序的速度。

並發(Concurrency):在新增Stream機制與Lambda的基礎之上,加入了一些新方法來支援聚集操作。

Nashorn引擎jjs:基於Nashorn引擎的命令列工具。它接受一些JavaScript原始碼為參數,並且執行這些原始碼。

類依賴分析器jdeps:可以顯示Java類的包層級或類層級的依賴。

JVM的PermGen空間被移除:取代它的是Metaspace(JEP 122)。 5.Optional

Optional實際上是個容器:它可以檔案類型T的值,或者僅僅儲存null。Optional提供很多有用的方法,這樣我們可以用Optional進行空值檢測。

        Person person = new Person();//        person = null;        Boolean flag = Optional.ofNullable(person).isPresent();        System.out.println("Full Name is set? " + flag);

如果Optional類的執行個體為非空值的話,isPresent()返回true,否從返回false。 5.Lambda運算式(函數式編程)

函數式編程可以說是 聲明式編程。(文章末尾有解釋。) 命令式編程:命令“機器”如何去做事情(how),這樣不管你想要的是什麼(what),它都會按照你的命令實現。 聲明式編程:告訴“機器”你想要的是什麼(what),讓機器想出如何去做(how)。

lambda運算式允許你通過運算式來代替功能介面。 lambda運算式就和方法一樣,它提供了一個正常的參數列表和一個使用這些參數的主體(body,可以是一個運算式或一個代碼塊)。
Lambda運算式還增強了集合庫。 Java SE 8添加了2個對集合資料進行大量操作的包: java.util.function 包以及 java.util.stream 包。 流(stream)就如同迭代器(iterator),但附加了許多額外的功能。 總的來說,lambda運算式和 stream 是自Java語言添加泛型(Generics)和註解(annotation)以來最大的變化。 Lambda 運算式簡單文法:

// 1. 不需要參數,傳回值為 5  () -> 5  // 2. 接收一個參數(數字類型),返回其2倍的值  x -> 2 * x  // 3. 接受2個參數(數字),並返回他們的差值  (x, y) -> x – y  // 4. 接收2個int型整數,返回他們的和  (int x, int y) -> x + y  // 5. 接受一個 string 對象,並在控制台列印,不返回任何值(看起來像是返回void)  (String s) -> System.out.print(s)  
Lambda 的for 迴圈
    //初始化資料    List<String> str = new ArrayList<>();        for (int i = 0; i < 10; i++) {            str.add(i + "");        }        //通過運算式輸出,如果知道是String 型就寫String 否則就寫範型,java會自動識別。         str.forEach((String) -> System.out.println(String+";")); str.forEach((String) -> {         System.out.println(String+";");         System.out.println(String+"附加的操作");         });        str.clear();

這樣寫就讓代碼變得簡單了。
匿名類可以使用lambda運算式來代替。 同樣,在實現Runnable介面時也可以這樣使用:

// 1.1使用匿名內部類  new Thread(new Runnable() {      @Override      public void run() {          System.out.println("Hello world !");      }  }).start();  // 1.2使用 lambda expression  new Thread(() -> System.out.println("Hello world !")).start();  // 2.1使用匿名內部類  Runnable race1 = new Runnable() {      @Override      public void run() {          System.out.println("Hello world !");      }  };  // 2.2使用 lambda expression  Runnable race2 = () -> System.out.println("Hello world !");  // 直接調用 run 方法(沒開新線程哦!)  race1.run();  race2.run();
使用Lambdas排序集合
//方式一,通過首字母排序List<String> str2 = Arrays.asList("abel", "don", "bruce", "sean");    str2.sort((e1, e2) -> e1.compareTo(e2)); // str2.forEach((String)->System.out.println(String+";"));    str2.forEach((e) -> System.out.println(e));//通過長度排序List<String> str3 = Arrays.asList("abel", "don", "bruce", "sean");        //長度從小到大排序        str3.sort((e1, e2) -> e1.length()-e2.length());         str3.forEach((e) -> System.out.println(e));

使用這種方式也可以實現排序

List<String> str3 = Arrays.asList("abel", "don", "bruce", "sean");          Comparator<String> sortByName=(String e1, String e2) -> e1.length()-e2.length();        str3.sort(sortByName); //長度從小到大排序        str3.forEach((e) -> System.out.println(e));
使用Lambdas和Streams

使用fileter 過濾顯示

List<String> str3 = Arrays.asList("abel", "don", "bruce", "sean");        //輸出長度大於3的        str3.stream().filter((String e1) -> (e1.length() > 3)).forEach((e) -> System.out.println(e));

結果如下
abel
bruce
sean

多個過濾器組合使用,也可以這樣單獨的定義過濾器

List<String> str3 = Arrays.asList("abel", "don", "bruce", "sean");        //定義過濾器        Predicate<String> lengthFilter = (String e1) -> (e1.length() > 3);        Predicate<String> conFilter = (String e1) -> (e1.contains("a"));        str3.stream().filter(lengthFilter).filter(conFilter).forEach((e) -> System.out.println(e));

還有limit 限定,最大最小值方法。

List<String> str3 = Arrays.asList("abel", "don", "bruce", "sean");//按首字母排序,輸出前三個    str3.stream().sorted((e1, e2) -> e1.compareTo(e2)).limit(3).forEach((e) -> System.out.println(e));        System.out.println("------------------------------------------------------------");        //輸出長度最長的        String max=str3.stream().max(( e1,e2) -> (e1.length() - e2.length())).get();        //輸出長度最短的        String min=str3.stream().min(( e1,e2) -> (e1.length() - e2.length())).get();System.out.println(max+"---"+min);  

stream 的並行計算和使用summaryStatistics方法獲得stream 中元素的各種摘要資料

List<String> str3 = Arrays.asList("abel", "don", "bruce", "sean");//並行計算        int sum=str3.stream().parallel().mapToInt(p->p.length()).sum();        System.out.println(sum);        //使用summaryStatistics方法獲得stream 中元素的各種摘要資料        IntSummaryStatistics sumstatis=str3.stream().mapToInt(p->p.length()).summaryStatistics();        System.out.println("求長度平均數"+sumstatis.getAverage()+"\n長度最小的"+sumstatis.getMin()+"\n長度最大的"+sumstatis.getMax()+"\n求總和"+sumstatis.getSum());

除此之外 Lambdas結合 map 方法,還可以使用 collect 方法來將我們的結果集放到一個字串,一個 Set 或一個TreeSet中這裡就不做解釋了 引用類的成員變數與局部變數

Lambda可以引用類的成員變數與局部變數(如果這些變數不是final的話,它們會被隱含的轉為final,這樣效率更高)。例如,下面兩個程式碼片段是等價的:

String separator = ",";Arrays.asList( "a", "b", "d" ).forEach(     ( String e ) -> System.out.print( e + separator ) );

和:

final String separator = ",";Arrays.asList( "a", "b", "d" ).forEach(     ( String e ) -> System.out.print( e + separator ) );
5. 我用Lambdas 舉的一些例子

測試類別。

package com.us;import java.util.*;import java.util.function.Predicate;import java.util.stream.Collectors;/** * Created by yangyibo on 16/12/26. */public class LambdaTest {    public static void main(String[] args) {//        forEachT();//        threadT();//        sortT();//        streamsFilterT();//        streamsCountT();//        personTComparator();//        boysAndGirls();        stringToIntT();    }    //Lambda 的for 迴圈    private static void forEachT() {        List<String> str = new ArrayList<>();        for (int i = 0; i < 10; i++) {            str.add(i + "");        }        str.forEach((String) -> System.out.println(String + ";"));        str.forEach((String) -> {            System.out.print(String + ";");            System.out.println(String + "附加的操作");        });        str.clear();    }    //匿名類 線程操作    private static void threadT() {        System.out.println("current--" + Thread.currentThread().getId());        //使用 lambda expression  開線程        new Thread(() -> System.out.println("Hello world Thread !---" + Thread.currentThread().getId())).start();        //使用匿名內部類   沒有開線程        Runnable race2 = () -> System.out.println("Hello world  Runnable !--" + Thread.currentThread().getId());        race2.run();    }    //Comparator 排序    private static void sortT() {        //方式一,通過首字母排序        List<String> str2 = Arrays.asList("abel", "don", "bruce", "sean");        str2.sort((e1, e2) -> e1.compareTo(e2));        str2.forEach((e) -> System.out.println(e));        System.out.println("--------------分割線--------------------");        //通過長度排序        List<String> str3 = Arrays.asList("abel", "don", "bruce", "sean");        //長度從小到大排序        str3.sort((e1, e2) -> e1.length() - e2.length());        str3.forEach((e) -> System.out.println(e));        System.out.println("--------------分割線--------------------");        //通過長度排序        List<String> str4 = Arrays.asList("abel", "don", "br

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.