1. 程式人生 > >JDK1.8 新特性(全)

JDK1.8 新特性(全)

https://blog.csdn.net/qq_29411737/article/details/80835658

JDK1.8 新特性(全)

2018年06月27日 22:01:54  閱讀數:6952

版權宣告:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/qq_29411737/article/details/80835658

JDK1.8 新特性

本文主要介紹了JDK1.8版本中的一些新特性,乃作者視訊觀後筆記,僅供參考。

jdk1.8新特性知識點:

  • Lambda表示式
  • 函式式介面
  • *方法引用和構造器呼叫
  • Stream API
  • 介面中的預設方法和靜態方法
  • 新時間日期API

在jdk1.8中對hashMap等map集合的資料結構優化。hashMap資料結構的優化 
原來的hashMap採用的資料結構是雜湊表(陣列+連結串列),hashMap預設大小是16,一個0-15索引的陣列,如何往裡面儲存元素,首先呼叫元素的hashcode 
方法,計算出雜湊碼值,經過雜湊演算法算成陣列的索引值,如果對應的索引處沒有元素,直接存放,如果有物件在,那麼比較它們的equals方法比較內容 
如果內容一樣,後一個value會將前一個value的值覆蓋,如果不一樣,在1.7的時候,後加的放在前面,形成一個連結串列,形成了碰撞,在某些情況下如果連結串列 
無限下去,那麼效率極低,碰撞是避免不了的 
載入因子:0.75,陣列擴容,達到總容量的75%,就進行擴容,但是無法避免碰撞的情況發生 
在1.8之後,在陣列+連結串列+紅黑樹來實現hashmap,當碰撞的元素個數大於8時 & 總容量大於64,會有紅黑樹的引入 
除了新增之後,效率都比連結串列高,1.8之後連結串列新進元素加到末尾 
ConcurrentHashMap (鎖分段機制),concurrentLevel,jdk1.8採用CAS演算法(無鎖演算法,不再使用鎖分段),陣列+連結串列中也引入了紅黑樹的使用

Lambda表示式

lambda表示式本質上是一段匿名內部類,也可以是一段可以傳遞的程式碼

先來體驗一下lambda最直觀的優點:簡潔程式碼

<span style="color:#000000"><code>  <span style="color:#880000 !important"><em>//匿名內部類</em></span>
  Comparator<span style="color:#4f4f4f !important"><</span><span style="color:#4f4f4f !important">Integer</span><span style="color:#4f4f4f !important">></span> cpt <span style="color:#4f4f4f !important">=</span> <span style="color:#006666 !important">new</span> Comparator<span style="color:#4f4f4f !important"><</span><span style="color:#4f4f4f !important">Integer</span><span style="color:#4f4f4f !important">></span>() {
      @Override
      <span style="color:#000088 !important">public</span> int compare(<span style="color:#4f4f4f !important">Integer</span> o1, <span style="color:#4f4f4f !important">Integer</span> o2) {
          <span style="color:#000088 !important">return</span> <span style="color:#4f4f4f !important">Integer</span><span style="color:#4f4f4f !important">.</span>compare(o1,o2);
      }
  };

  TreeSet<span style="color:#4f4f4f !important"><</span><span style="color:#4f4f4f !important">Integer</span><span style="color:#4f4f4f !important">></span> <span style="color:#4f4f4f !important">set</span> <span style="color:#4f4f4f !important">=</span> <span style="color:#006666 !important">new</span> TreeSet<span style="color:#4f4f4f !important"><></span>(cpt);

  System<span style="color:#4f4f4f !important">.</span>out<span style="color:#4f4f4f !important">.</span>println(<span style="color:#009900 !important">"========================="</span>);

  <span style="color:#880000 !important"><em>//使用lambda表示式</em></span>
  Comparator<span style="color:#4f4f4f !important"><</span><span style="color:#4f4f4f !important">Integer</span><span style="color:#4f4f4f !important">></span> cpt2 <span style="color:#4f4f4f !important">=</span> (x,y) <span style="color:#4f4f4f !important">-> </span><span style="color:#4f4f4f !important">Integer</span><span style="color:#4f4f4f !important">.</span>compare(x,y);
  TreeSet<span style="color:#4f4f4f !important"><</span><span style="color:#4f4f4f !important">Integer</span><span style="color:#4f4f4f !important">></span> set2 <span style="color:#4f4f4f !important">=</span> <span style="color:#006666 !important">new</span> TreeSet<span style="color:#4f4f4f !important"><></span>(cpt2);</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

只需要一行程式碼,極大減少程式碼量!!

這樣一個場景,在商城瀏覽商品資訊時,經常會有條件的進行篩選瀏覽,例如要選顏色為紅色的、價格小於8000千的….

<span style="color:#000000"><code><span style="color:#880000 !important"><em>// 篩選顏色為紅色</em></span>
<span style="color:#000088 !important">public</span>  <span style="color:#000088 !important">List</span><Product> filterProductByColor(<span style="color:#000088 !important">List</span><Product> <span style="color:#000088 !important">list</span>){
    <span style="color:#000088 !important">List</span><Product> prods = <span style="color:#000088 !important">new</span> ArrayList<>();
    <span style="color:#000088 !important">for</span> (Product product : <span style="color:#000088 !important">list</span>){
        <span style="color:#000088 !important">if</span> (<span style="color:#009900 !important">"紅色"</span>.equals(product.getColor())){
            prods.add(product);
        }
    }
    <span style="color:#000088 !important">return</span> prods;
 }

<span style="color:#880000 !important"><em>// 篩選價格小於8千的</em></span>
<span style="color:#000088 !important">public</span>  <span style="color:#000088 !important">List</span><Product> filterProductByPrice(<span style="color:#000088 !important">List</span><Product> <span style="color:#000088 !important">list</span>){
    <span style="color:#000088 !important">List</span><Product> prods = <span style="color:#000088 !important">new</span> ArrayList<>();
    <span style="color:#000088 !important">for</span> (Product product : <span style="color:#000088 !important">list</span>){
        <span style="color:#000088 !important">if</span> (product.getPrice() < <span style="color:#006666 !important">8000</span>){
            prods.add(product);
        }
    }
    <span style="color:#000088 !important">return</span> prods;
 }</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

我們發現實際上這些過濾方法的核心就只有if語句中的條件判斷,其他均為模版程式碼,每次變更一下需求,都需要新增一個方法,然後複製黏貼,假設這個過濾方法有幾百行,那麼這樣的做法難免笨拙了一點。如何進行優化呢?

優化一:使用設計模式

定義一個MyPredicate介面

<span style="color:#000000"><code><span style="color:#000088 !important">public</span> <span style="color:#000088 !important">interface</span> MyPredicate <T> {
    boolean test(T t);
}</code></span>
  • 1
  • 2
  • 3

如果想要篩選顏色為紅色的商品,定義一個顏色過濾類

<span style="color:#000000"><code><span style="color:#000088 !important">public</span> <span style="color:#000088 !important">class</span> <span style="color:#4f4f4f !important">ColorPredicate</span> <span style="color:#000088 !important">implements</span> <span style="color:#4f4f4f !important">MyPredicate</span> <<span style="color:#4f4f4f !important">Product</span>> {

     <span style="color:#000088 !important">private</span> <span style="color:#000088 !important">static</span> <span style="color:#000088 !important">final</span> String RED = <span style="color:#009900 !important">"紅色"</span>;

     @Override
     <span style="color:#000088 !important">public</span> <span style="color:#000088 !important">boolean</span> test(Product product) {
         <span style="color:#000088 !important">return</span> RED.equals(product.getColor());
     }</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

定義過濾方法,將過濾介面當做引數傳入,這樣這個過濾方法就不用修改,在實際呼叫的時候將具體的實現類傳入即可。

<span style="color:#000000"><code><span style="color:#000088 !important">public</span> <span style="color:#000088 !important">List</span><Product> filterProductByPredicate(<span style="color:#000088 !important">List</span><Product> <span style="color:#000088 !important">list</span>,MyPredicate<Product> mp){
        <span style="color:#000088 !important">List</span><Product> prods = <span style="color:#000088 !important">new</span> ArrayList<>();
        <span style="color:#000088 !important">for</span> (Product prod : <span style="color:#000088 !important">list</span>){
            <span style="color:#000088 !important">if</span> (mp.test(prod)){
                prods.add(prod);
            }
        }
        <span style="color:#000088 !important">return</span> prods;
    }</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

例如,如果想要篩選價格小於8000的商品,那麼新建一個價格過濾類既可

<span style="color:#000000"><code><span style="color:#000088 !important">public</span> <span style="color:#000088 !important">class</span> <span style="color:#4f4f4f !important">PricePredicate</span> <span style="color:#000088 !important">implements</span> <span style="color:#4f4f4f !important">MyPredicate</span><<span style="color:#4f4f4f !important">Product</span>> {
    @Override
    <span style="color:#000088 !important">public</span> <span style="color:#000088 !important">boolean</span> test(Product product) {
        <span style="color:#000088 !important">return</span> product.getPrice() < <span style="color:#006666 !important">8000</span>;
    }
}</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

這樣實現的話可能有人會說,每次變更需求都需要新建一個實現類,感覺還是有點繁瑣呀,那麼再來優化一下

優化二:使用匿名內部類

定義過濾方法:

<span style="color:#000000"><code><span style="color:#000088 !important">public</span> <span style="color:#000088 !important">List</span><Product> filterProductByPredicate(<span style="color:#000088 !important">List</span><Product> <span style="color:#000088 !important">list</span>,MyPredicate<Product> mp){
        <span style="color:#000088 !important">List</span><Product> prods = <span style="color:#000088 !important">new</span> ArrayList<>();
        <span style="color:#000088 !important">for</span> (Product prod : <span style="color:#000088 !important">list</span>){
            <span style="color:#000088 !important">if</span> (mp.test(prod)){
                prods.add(prod);
            }
        }
        <span style="color:#000088 !important">return</span> prods;
    }</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

呼叫過濾方法的時候:

<span style="color:#000000"><code><span style="color:#880000 !important"><em>// 按價格過濾</em></span>
<span style="color:#000088 !important">public</span> <span style="color:#000088 !important">void</span> <span style="color:#009900 !important">test2</span>(){
    filterProductByPredicate(proList, <span style="color:#000088 !important">new</span> MyPredicate<Product>() {
        <span style="color:#9b859d !important">@Override</span>
        <span style="color:#000088 !important">public</span> <span style="color:#000088 !important">boolean</span> <span style="color:#009900 !important">test</span>(Product product) {
            <span style="color:#000088 !important">return</span> product.getPrice() < <span style="color:#006666 !important">8000</span>;
        }
    });
}

 <span style="color:#880000 !important"><em>// 按顏色過濾</em></span>
 <span style="color:#000088 !important">public</span> <span style="color:#000088 !important">void</span> <span style="color:#009900 !important">test3</span>(){
     filterProductByPredicate(proList, <span style="color:#000088 !important">new</span> MyPredicate<Product>() {
         <span style="color:#9b859d !important">@Override</span>
         <span style="color:#000088 !important">public</span> <span style="color:#000088 !important">boolean</span> <span style="color:#009900 !important">test</span>(Product product) {
             <span style="color:#000088 !important">return</span> <span style="color:#009900 !important">"紅色"</span>.equals(product.getColor());
         }
     });
 }</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

使用匿名內部類,就不需要每次都新建一個實現類,直接在方法內部實現。看到匿名內部類,不禁想起了Lambda表示式。

優化三:使用lambda表示式

定義過濾方法:

<span style="color:#000000"><code><span style="color:#000088 !important">public</span> <span style="color:#000088 !important">List</span><Product> filterProductByPredicate(<span style="color:#000088 !important">List</span><Product> <span style="color:#000088 !important">list</span>,MyPredicate<Product> mp){
        <span style="color:#000088 !important">List</span><Product> prods = <span style="color:#000088 !important">new</span> ArrayList<>();
        <span style="color:#000088 !important">for</span> (Product prod : <span style="color:#000088 !important">list</span>){
            <span style="color:#000088 !important">if</span> (mp.test(prod)){
                prods.add(prod);
            }
        }
        <span style="color:#000088 !important">return</span> prods;
    }</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

使用lambda表示式進行過濾

<span style="color:#000000"><code>@Test
public void test4(){
      List<Product> products = filterProductByPredicate<span style="color:#4f4f4f !important">(proList, (p) -> p.getPrice() < <span style="color:#006666 !important">8000</span>)</span>;
      <span style="color:#009900 !important">for</span> <span style="color:#4f4f4f !important">(Product pro : products)</span>{
          <span style="color:#009900 !important">System</span>.<span style="color:#009900 !important">out</span>.<span style="color:#009900 !important">println</span><span style="color:#4f4f4f !important">(pro)</span>;
      }
  }</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在jdk1.8中還有更加簡便的操作 Stream API

優化四:使用Stream API

甚至不用定義過濾方法,直接在集合上進行操作

<span style="color:#000000"><code><span style="color:#008800 !important">//</span> 使用jdk1<span style="color:#006666 !important">.8</span>中的Stream API進行集合的操作
@Test
public void test(){
    <span style="color:#008800 !important">//</span> 根據價格過濾
    proList.stream()
           .fliter<span style="color:#4f4f4f !important">((p) -> p.getPrice() <<span style="color:#006666 !important">8000</span>)</span>
           .<span style="color:#009900 !important">limit</span><span style="color:#4f4f4f !important">(<span style="color:#006666 !important">2</span>)</span>
           .<span style="color:#009900 !important">forEach</span><span style="color:#4f4f4f !important">(System.out::println)</span>;

    // 根據顏色過濾
    <span style="color:#009900 !important">proList</span>.<span style="color:#009900 !important">stream</span><span style="color:#4f4f4f !important">()</span>
           .<span style="color:#009900 !important">fliter</span><span style="color:#4f4f4f !important">((p) -> <span style="color:#009900 !important">"紅色"</span>.equals(p.getColor()))</span>
           .<span style="color:#009900 !important">forEach</span><span style="color:#4f4f4f !important">(System.out::println)</span>;

    // 遍歷輸出商品名稱
    <span style="color:#009900 !important">proList</span>.<span style="color:#009900 !important">stream</span><span style="color:#4f4f4f !important">()</span>
           .<span style="color:#009900 !important">map</span><span style="color:#4f4f4f !important">(Product::getName)</span>
           .<span style="color:#009900 !important">forEach</span><span style="color:#4f4f4f !important">(System.out::println)</span>;
}</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

Lmabda表示式的語法總結: () -> ();

前置 語法
無引數無返回值 () -> System.out.println(“Hello WOrld”)
有一個引數無返回值 (x) -> System.out.println(x)
有且只有一個引數無返回值 x -> System.out.println(x)
有多個引數,有返回值,有多條lambda體語句 (x,y) -> {System.out.println(“xxx”);return xxxx;};
有多個引數,有返回值,只有一條lambda體語句 (x,y) -> xxxx

口訣:左右遇一省括號,左側推斷型別省

注:當一個介面中存在多個抽象方法時,如果使用lambda表示式,並不能智慧匹配對應的抽象方法,因此引入了函式式介面的概念

函式式介面

函式式介面的提出是為了給Lambda表示式的使用提供更好的支援。

什麼是函式式介面? 
簡單來說就是隻定義了一個抽象方法的介面(Object類的public方法除外),就是函式式介面,並且還提供了註解:@FunctionalInterface

常見的四大函式式介面

  • Consumer 《T》:消費型介面,有參無返回值
<span style="color:#000000"><code>    <span style="color:#9b859d !important">@Test</span>
    <span style="color:#000088 !important">public</span> <span style="color:#000088 !important">void</span> <span style="color:#009900 !important">test</span>(){
        changeStr(<span style="color:#009900 !important">"hello"</span>,(str) -> System.out.println(str));
    }

    <span style="color:#880000 !important">/**
     *  Consumer<T> 消費型介面
     *<span style="color:#4f4f4f !important"> @param</span> str
     *<span style="color:#4f4f4f !important"> @param</span> con
     */</span>
    <span style="color:#000088 !important">public</span> <span style="color:#000088 !important">void</span> <span style="color:#009900 !important">changeStr</span>(String str, Consumer<String> con){
        con.accept(str);
    }</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • Supplier 《T》:供給型介面,無參有返回值
<span style="color:#000000"><code>    <span style="color:#9b859d !important">@Test</span>
    <span style="color:#000088 !important">public</span> <span style="color:#000088 !important">void</span> <span style="color:#009900 !important">test2</span>(){
        String value = getValue(() -> <span style="color:#009900 !important">"hello"</span>);
        System.out.println(value);
    }

    <span style="color:#880000 !important">/**
     *  Supplier<T> 供給型介面
     *<span style="color:#4f4f4f !important"> @param</span> sup
     *<span style="color:#4f4f4f !important"> @return</span>
     */</span>
    <span style="color:#000088 !important">public</span> String <span style="color:#009900 !important">getValue</span>(Supplier<String> sup){
        <span style="color:#000088 !important">return</span> sup.get();
    }</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • Function 《T,R》::函式式介面,有參有返回值
<span style="color:#000000"><code>    <span style="color:#9b859d !important">@Test</span>
    <span style="color:#000088 !important">public</span> <span style="color:#000088 !important">void</span> <span style="color:#009900 !important">test3</span>(){
        Long result = changeNum(<span style="color:#006666 !important">100</span>L, (x) -> x + <span style="color:#006666 !important">200</span>L);
        System.out.println(result);
    }

    <span style="color:#880000 !important">/**
     *  Function<T,R> 函式式介面
     *<span style="color:#4f4f4f !important"> @param</span> num
     *<span style="color:#4f4f4f !important"> @param</span> fun
     *<span style="color:#4f4f4f !important"> @return</span>
     */</span>
    <span style="color:#000088 !important">public</span> Long <span style="color:#009900 !important">changeNum</span>(Long num, Function<Long, Long> fun){
        <span style="color:#000088 !important">return</span> fun.apply(num);
    }</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • Predicate《T》: 斷言型介面,有參有返回值,返回值是boolean型別
<span style="color:#000000"><code><span style="color:#000088 !important">public</span> <span style="color:#000088 !important">void</span> <span style="color:#009900 !important">test4</span>(){
        <span style="color:#000088 !important">boolean</span> result = changeBoolean(<span style="color:#009900 !important">"hello"</span>, (str) -> str.length() > <span style="color:#006666 !important">5</span>);
        System.out.println(result);
    }

    <span style="color:#880000 !important">/**
     *  Predicate<T> 斷言型介面
     *<span style="color:#4f4f4f !important"> @param</span> str
     *<span style="color:#4f4f4f !important"> @param</span> pre
     *<span style="color:#4f4f4f !important"> @return</span>
     */</span>
    <span style="color:#000088 !important">public</span> <span style="color:#000088 !important">boolean</span> <span style="color:#009900 !important">changeBoolean</span>(String str, Predicate<String> pre){
        <span style="color:#000088 !important">return</span> pre.test(str);
    }</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

在四大核心函式式介面基礎上,還提供了諸如BiFunction、BinaryOperation、toIntFunction等擴充套件的函式式介面,都是在這四種函式式介面上擴充套件而來的,不做贅述。

總結:函式式介面的提出是為了讓我們更加方便的使用lambda表示式,不需要自己再手動建立一個函式式介面,直接拿來用就好了,貼

方法引用

若lambda體中的內容有方法已經實現了,那麼可以使用“方法引用” 
也可以理解為方法引用是lambda表示式的另外一種表現形式並且其語法比lambda表示式更加簡單

(a) 方法引用 
三種表現形式: 
1. 物件::例項方法名 
2. 類::靜態方法名 
3. 類::例項方法名 (lambda引數列表中第一個引數是例項方法的呼叫 者,第二個引數是例項方法的引數時可用)

<span style="color:#000000"><code> <span style="color:#000088 !important">public</span> <span style="color:#006666 !important">void</span> test() {
        <span style="color:#880000 !important"><em>/**
        *注意:
        *   1.lambda體中呼叫方法的引數列表與返回值型別,要與函式式介面中抽象方法的函式列表和返回值型別保持一致!
        *   2.若lambda引數列表中的第一個引數是例項方法的呼叫者,而第二個引數是例項方法的引數時,可以使用ClassName::method
        *
        */</em></span>
        Consumer<span style="color:#4f4f4f !important"><</span><span style="color:#4f4f4f !important">Integer</span><span style="color:#4f4f4f !important">></span> con <span style="color:#4f4f4f !important">=</span> (x) <span style="color:#4f4f4f !important">-> </span>System<span style="color:#4f4f4f !important">.</span>out<span style="color:#4f4f4f !important">.</span>println(x);
        con<span style="color:#4f4f4f !important">.</span>accept(<span style="color:#006666 !important">100</span>);

        <span style="color:#880000 !important"><em>// 方法引用-物件::例項方法</em></span>
        Consumer<span style="color:#4f4f4f !important"><</span><span style="color:#4f4f4f !important">Integer</span><span style="color:#4f4f4f !important">></span> con2 <span style="color:#4f4f4f !important">=</span> System<span style="color:#4f4f4f !important">.</span>out<span style="color:#006666 !important">::println</span>;
        con2<span style="color:#4f4f4f !important">.</span>accept(<span style="color:#006666 !important">200</span>);

        <span style="color:#880000 !important"><em>// 方法引用-類名::靜態方法名</em></span>
        BiFunction<span style="color:#4f4f4f !important"><</span><span style="color:#4f4f4f !important">Integer</span>, <span style="color:#4f4f4f !important">Integer</span>, <span style="color:#4f4f4f !important">Integer</span><span style="color:#4f4f4f !important">></span> biFun <span style="color:#4f4f4f !important">=</span> (x, y) <span style="color:#4f4f4f !important">-> </span><span style="color:#4f4f4f !important">Integer</span><span style="color:#4f4f4f !important">.</span>compare(x, y);
        BiFunction<span style="color:#4f4f4f !important"><</span><span style="color:#4f4f4f !important">Integer</span>, <span style="color:#4f4f4f !important">Integer</span>, <span style="color:#4f4f4f !important">Integer</span><span style="color:#4f4f4f !important">></span> biFun2 <span style="color:#4f4f4f !important">=</span> <span style="color:#4f4f4f !important">Integer</span><span style="color:#006666 !important">::compare</span>;
        <span style="color:#4f4f4f !important">Integer</span> result <span style="color:#4f4f4f !important">=</span> biFun2<span style="color:#4f4f4f !important">.</span>apply(<span style="color:#006666 !important">100</span>, <span style="color:#006666 !important">200</span>);

        <span style="color:#880000 !important"><em>// 方法引用-類名::例項方法名</em></span>
        BiFunction<span style="color:#4f4f4f !important"><</span><span style="color:#4f4f4f !important">String</span>, <span style="color:#4f4f4f !important">String</span>, Boolean<span style="color:#4f4f4f !important">></span> fun1 <span style="color:#4f4f4f !important">=</span> (str1, str2) <span style="color:#4f4f4f !important">-> </span>str1<span style="color:#4f4f4f !important">.</span><span style="color:#000088 !important">equals</span>(str2);
        BiFunction<span style="color:#4f4f4f !important"><</span><span style="color:#4f4f4f !important">String</span>, <span style="color:#4f4f4f !important">String</span>, Boolean<span style="color:#4f4f4f !important">></span> fun2 <span style="color:#4f4f4f !important">=</span> <span style="color:#4f4f4f !important">String</span><span style="color:#006666 !important">::equals</span>;
        Boolean result2 <span style="color:#4f4f4f !important">=</span> fun2<span style="color:#4f4f4f !important">.</span>apply(<span style="color:#009900 !important">"hello"</span>, <span style="color:#009900 !important">"world"</span>);
        System<span style="color:#4f4f4f !important">.</span>out<span style="color:#4f4f4f !important">.</span>println(result2);
    }</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

(b)構造器引用 
格式:ClassName::new

<span style="color:#000000"><code><span style="color:#000088 !important">public</span> <span style="color:#000088 !important">void</span> <span style="color:#009900 !important">test2</span>() {

        <span style="color:#880000 !important"><em>// 構造方法引用  類名::new</em></span>
        Supplier<Employee> sup = () -> <span style="color:#000088 !important">new</span> Employee();
        System.<span style="color:#000088 !important">out</span>.println(sup.<span style="color:#000088 !important">get</span>());
        Supplier<Employee> sup2 = Employee::<span style="color:#000088 !important">new</span>;
        System.<span style="color:#000088 !important">out</span>.println(sup2.<span style="color:#000088 !important">get</span>());

        <span style="color:#880000 !important"><em>// 構造方法引用 類名::new (帶一個引數)</em></span>
        Function<Integer, Employee> fun = (x) -> <span style="color:#000088 !important">new</span> Employee(x);
        Function<Integer, Employee> fun2 = Employee::<span style="color:#000088 !important">new</span>;
        System.<span style="color:#000088 !important">out</span>.println(fun2.apply(<span style="color:#006666 !important">100</span>));
 }</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

(c)陣列引用

格式:Type[]::new

<span style="color:#000000"><code>public <span style="color:#000088 !important">void</span> test(){
        <span style="color:#880000 !important"><em>// 陣列引用</em></span>
        <span style="color:#4f4f4f !important">Function</span><Integer, <span style="color:#4f4f4f !important">String</span>[]> fun = (x) -> <span style="color:#000088 !important">new</span> <span style="color:#4f4f4f !important">String</span>[x];
        <span style="color:#4f4f4f !important">Function</span><Integer, <span style="color:#4f4f4f !important">String</span>[]> fun2 = <span style="color:#4f4f4f !important">String</span>[]::<span style="color:#000088 !important">new</span>;
        <span style="color:#4f4f4f !important">String</span>[] strArray = fun2.apply(<span style="color:#006666 !important">10</span>);
        Arrays.stream(strArray).forEach(System.out::println);
}</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Stream API

Stream操作的三個步驟

  • 建立stream
  • 中間操作(過濾、map)
  • 終止操作

stream的建立:

<span style="color:#000000"><code>    <span style="color:#880000 !important"><em>// 1,校驗通過Collection 系列集合提供的stream()或者paralleStream()</em></span>
    List<<span style="color:#4f4f4f !important">String</span>> list = <span style="color:#000088 !important">new</span> ArrayList<>();
    Strean<<span style="color:#4f4f4f !important">String</span>> stream1 = list.stream();

    <span style="color:#880000 !important"><em>// 2.通過Arrays的靜態方法stream()獲取陣列流</em></span>
    <span style="color:#4f4f4f !important">String</span>[] str = <span style="color:#000088 !important">new</span> <span style="color:#4f4f4f !important">String</span>[<span style="color:#006666 !important">10</span>];
    Stream<<span style="color:#4f4f4f !important">String</span>> stream2 = Arrays.stream(str);

    <span style="color:#880000 !important"><em>// 3.通過Stream類中的靜態方法of</em></span>
    Stream<<span style="color:#4f4f4f !important">String</span>> stream3 = Stream.of(<span style="color:#009900 !important">"aa"</span>,<span style="color:#009900 !important">"bb"</span>,<span style="color:#009900 !important">"cc"</span>);

    <span style="color:#880000 !important"><em>// 4.建立無限流</em></span>
    <span style="color:#880000 !important"><em>// 迭代</em></span>
    Stream<Integer> stream4 = Stream.iterate(<span style="color:#006666 !important">0</span>,(x) -> x+<span style="color:#006666 !important">2</span>);

    <span style="color:#880000 !important"><em>//生成</em></span>
    Stream.generate(() -><span style="color:#4f4f4f !important">Math</span>.random());</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

Stream的中間操作:

<span style="color:#000000"><code><span style="color:#880000 !important">/**
   * 篩選 過濾  去重
   */</span>
  emps.stream()
          .filter(e -> e.getAge() > <span style="color:#006666 !important">10</span>)
          .limit(<span style="color:#006666 !important">4</span>)
          .skip(<span style="color:#006666 !important">4</span>)
          <span style="color:#880000 !important"><em>// 需要流中的元素重寫hashCode和equals方法</em></span>
          .distinct()
          .forEach(System.out::println);


  <span style="color:#880000 !important">/**
   *  生成新的流 通過map對映
   */</span>
  emps.stream()
          .map((e) -> e.getAge())
          .forEach(System.out::println);


  <span style="color:#880000 !important">/**
   *  自然排序  定製排序
   */</span>
  emps.stream()
          .sorted((e1 ,e2) -> {
              <span style="color:#000088 !important">if</span> (e1.getAge().equals(e2.getAge())){
                  <span style="color:#000088 !important">return</span> e1.getName().compareTo(e2.getName());
              } <span style="color:#000088 !important">else</span>{
                  <span style="color:#000088 !important">return</span> e1.getAge().compareTo(e2.getAge());
              }
          })
          .forEach(System.out::println);
</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

Stream的終止操作:

<span style="color:#000000"><code> /**
         *      查詢和匹配
         *          allMatch-檢查是否匹配所有元素
         *          anyMatch-檢查是否至少匹配一個元素
         *          noneMatch-檢查是否沒有匹配所有元素
         *          findFirst-返回第一個元素
         *          findAny-返回當前流中的任意元素
         *          count-返回流中元素的總個數
         *          max-返回流中最大值
         *          min-返回流中最小值
         */

        /**
         *  檢查是否匹配元素
         */
        boolean b1 = emps.stream()
                .allMatch<span style="color:#4f4f4f !important">((e) -> e.getStatus().equals(Employee.Status.BUSY))</span>;
        <span style="color:#009900 !important">System</span>.<span style="color:#009900 !important">out</span>.<span style="color:#009900 !important">println</span><span style="color:#4f4f4f !important">(b1)</span>;

        <span style="color:#009900 !important">boolean</span> <span style="color:#009900 !important">b2</span> = <span style="color:#009900 !important">emps</span>.<span style="color:#009900 !important">stream</span><span style="color:#4f4f4f !important">()</span>
                .<span style="color:#009900 !important">anyMatch</span><span style="color:#4f4f4f !important">((e) -> e.getStatus().equals(Employee.Status.BUSY))</span>;
        <span style="color:#009900 !important">System</span>.<span style="color:#009900 !important">out</span>.<span style="color:#009900 !important">println</span><span style="color:#4f4f4f !important">(b2)</span>;

        <span style="color:#009900 !important">boolean</span> <span style="color:#009900 !important">b3</span> = <span style="color:#009900 !important">emps</span>.<span style="color:#009900 !important">stream</span><span style="color:#4f4f4f !important">()</span>
                .<span style="color:#009900 !important">noneMatch</span><span style="color:#4f4f4f !important">((e) -> e.getStatus().equals(Employee.Status.BUSY))</span>;
        <span style="color:#009900 !important">System</span>.<span style="color:#009900 !important">out</span>.<span style="color:#009900 !important">println</span><span style="color:#4f4f4f !important">(b3)</span>;

        <span style="color:#009900 !important">Optional</span><<span style="color:#009900 !important">Employee</span>> <span style="color:#009900 !important">opt</span> = <span style="color:#009900 !important">emps</span>.<span style="color:#009900 !important">stream</span><span style="color:#4f4f4f !important">()</span>
                .<span style="color:#009900 !important">findFirst</span><span style="color:#4f4f4f !important">()</span>;
        <span style="color:#009900 !important">System</span>.<span style="color:#009900 !important">out</span>.<span style="color:#009900 !important">println</span><span style="color:#4f4f4f !important">(opt.get())</span>;

        // 並行流
        <span style="color:#009900 !important">Optional</span><<span style="color:#009900 !important">Employee</span>> <span style="color:#009900 !important">opt2</span> = <span style="color:#009900 !important">emps</span>.<span style="color:#009900 !important">parallelStream</span><span style="color:#4f4f4f !important">()</span>
                .<span style="color:#009900 !important">findAny</span><span style="color:#4f4f4f !important">()</span>;
        <span style="color:#009900 !important">System</span>.<span style="color:#009900 !important">out</span>.<span style="color:#009900 !important">println</span><span style="color:#4f4f4f !important">(opt2.get())</span>;

        <span style="color:#009900 !important">long</span> <span style="color:#009900 !important">count</span> = <span style="color:#009900 !important">emps</span>.<span style="color:#009900 !important">stream</span><span style="color:#4f4f4f !important">()</span>
                .<span style="color:#009900 !important">count</span><span style="color:#4f4f4f !important">()</span>;
        <span style="color:#009900 !important">System</span>.<span style="color:#009900 !important">out</span>.<span style="color:#009900 !important">println</span><span style="color:#4f4f4f !important">(count)</span>;

        <span style="color:#009900 !important">Optional</span><<span style="color:#009900 !important">Employee</span>> <span style="color:#009900 !important">max</span> = <span style="color:#009900 !important">emps</span>.<span style="color:#009900 !important">stream</span><span style="color:#4f4f4f !important">()</span>
                .<span style="color:#009900 !important">max</span><span style="color:#4f4f4f !important">((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))</span>;
        <span style="color:#009900 !important">System</span>.<span style="color:#009900 !important">out</span>.<span style="color:#009900 !important">println</span><span style="color:#4f4f4f !important">(max.get())</span>;

        <span style="color:#009900 !important">Optional</span><<span style="color:#009900 !important">Employee</span>> <span style="color:#009900 !important">min</span> = <span style="color:#009900 !important">emps</span>.<span style="color:#009900 !important">stream</span><span style="color:#4f4f4f !important">()</span>
                .<span style="color:#009900 !important">min</span><span style="color:#4f4f4f !important">((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))</span>;
        <span style="color:#009900 !important">System</span>.<span style="color:#009900 !important">out</span>.<span style="color:#009900 !important">println</span><span style="color:#4f4f4f !important">(min.get())</span>;</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

還有功能比較強大的兩個終止操作 reduce和collect 
reduce操作: reduce:(T identity,BinaryOperator)/reduce(BinaryOperator)-可以將流中元素反覆結合起來,得到一個值

<span style="color:#000000"><code>         /**
         *  reduce :規約操作
         */
        List<Integer> list = Arrays.asList(<span style="color:#006666 !important">1</span>,<span style="color:#006666 !important">2</span>,<span style="color:#006666 !important">3</span>,<span style="color:#006666 !important">4</span>,<span style="color:#006666 !important">5</span>,<span style="color:#006666 !important">6</span>,<span style="color:#006666 !important">7</span>,<span style="color:#006666 !important">8</span>,<span style="color:#006666 !important">9</span>,<span style="color:#006666 !important">10</span>);
        Integer count2 = list.stream()
                .reduce<span style="color:#4f4f4f !important">(<span style="color:#006666 !important">0</span>, (x, y) -> x + y)</span>;
        <span style="color:#009900 !important">System</span>.<span style="color:#009900 !important">out</span>.<span style="color:#009900 !important">println</span><span style="color:#4f4f4f !important">(count2)</span>;

        <span style="color:#009900 !important">Optional</span><<span style="color:#009900 !important">Double</span>> <span style="color:#009900 !important">sum</span> = <span style="color:#009900 !important">emps</span>.<span style="color:#009900 !important">stream</span><span style="color:#4f4f4f !important">()</span>
                .<span style="color:#009900 !important">map</span><span style="color:#4f4f4f !important">(Employee::getSalary)</span>
                .<span style="color:#009900 !important">reduce</span><span style="color:#4f4f4f !important">(Double::sum)</span>;
        <span style="color:#009900 !important">System</span>.<span style="color:#009900 !important">out</span>.<span style="color:#009900 !important">println</span><span style="color:#4f4f4f !important">(sum)</span>;
</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

collect操作:Collect-將流轉換為其他形式,接收一個Collection介面的實現,用於給Stream中元素做彙總的方法

<span style="color:#000000"><code>        <span style="color:#880000 !important">/**
         *  collect:收集操作
         */</span>

        List<Integer> ageList = emps.stream()
                .map(Employee::getAge)
                .collect(Collectors.toList());
        ageList.stream().forEach(System.out::println);</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

並行流和序列流

在jdk1.8新的stream包中針對集合的操作也提供了並行操作流和序列操作流。並行流就是把內容切割成多個數據塊,並且使用多個執行緒分別處理每個資料塊的內容。Stream api中宣告可以通過parallel()與sequential()方法在並行流和序列流之間進行切換。 
jdk1.8並行流使用的是fork/join框架進行並行操作

ForkJoin框架

Fork/Join 框架:就是在必要的情況下,將一個大任務,進行拆分(fork)成若干個小任務(拆到不可再拆時),再將一個個的小任務運算的結果進行 join 彙總。 
關鍵字:遞迴分合、分而治之。 
採用 “工作竊取”模式(work-stealing): 
當執行新的任務時它可以將其拆分分成更小的任務執行,並將小任務加到線 
程佇列中,然後再從一個隨機執行緒的佇列中偷一個並把它放在自己的佇列中 
相對於一般的執行緒池實現,fork/join框架的優勢體現在對其中包含的任務的 
處理方式上.在一般的執行緒池中,如果一個執行緒正在執行的任務由於某些原因 
無法繼續執行,那麼該執行緒會處於等待狀態.而在fork/join框架實現中,如果 
某個子問題由於等待另外一個子問題的完成而無法繼續執行.那麼處理該子 
問題的執行緒會主動尋找其他尚未執行的子問題來執行.這種方式減少了執行緒 
的等待時間,提高了效能.。

<span style="color:#000000"><code><span style="color:#880000 !important">/**
 * 要想使用Fark—Join,類必須繼承
 * RecursiveAction(無返回值)
 * Or
 * RecursiveTask(有返回值)
*
*/</span>
public <span style="color:#000088 !important">class</span> <span style="color:#4f4f4f !important">ForkJoin</span> <span style="color:#000088 !important">extends</span> <span style="color:#4f4f4f !important">RecursiveTask</span><<span style="color:#4f4f4f !important">Long</span>> {

    <span style="color:#880000 !important">/**
     * 要想使用Fark—Join,類必須繼承RecursiveAction(無返回值) 或者
     * RecursiveTask(有返回值)
     *
     * <span style="color:#4f4f4f !important">@author</span> Wuyouxin
     */</span>
    <span style="color:#000088 !important">private</span> static <span style="color:#000088 !important">final</span> long serialVersionUID = <span style="color:#006666 !important">23423422</span>L;

    <span style="color:#000088 !important">private</span> long start;
    <span style="color:#000088 !important">private</span> long end;

    public ForkJoin() {
    }

    public ForkJoin(long start, long end) {
        <span style="color:#000088 !important">this</span>.start = start;
        <span style="color:#000088 !important">this</span>.end = end;
    }

    <span style="color:#880000 !important"><em>// 定義闕值</em></span>
    <span style="color:#000088 !important">private</span> static <span style="color:#000088 !important">final</span> long THRESHOLD = <span style="color:#006666 !important">10000</span>L;

    <span style="color:#9b859d !important">@Override</span>
    <span style="color:#000088 !important">protected</span> Long compute() {
        <span style="color:#000088 !important">if</span> (end - start <= THRESHOLD) {
            long sum = <span style="color:#006666 !important">0</span>;
            <span style="color:#000088 !important">for</span> (long i = start; i < end; i++) {
                sum += i;
            }
            <span style="color:#000088 !important">return</span> sum;
        } <span style="color:#000088 !important">else</span> {
            long middle = (end - start) / <span style="color:#006666 !important">2</span>;
            ForkJoin left = <span style="color:#000088 !important">new</span> ForkJoin(start, middle);
            <span style="color:#880000 !important"><em>//拆分子任務,壓入執行緒佇列</em></span>
            left.fork();
            ForkJoin right = <span style="color:#000088 !important">new</span> ForkJoin(middle + <span style="color:#006666 !important">1</span>, end);
            right.fork();

            <span style="color:#880000 !important"><em>//合併並返回</em></span>
            <span style="color:#000088 !important">return</span> left.join() + right.join();
        }
    }

    <span style="color:#880000 !important">/**
     * 實現數的累加
     */</span>
    <span style="color:#9b859d !important">@Test</span>
    public void test1() {
        <span style="color:#880000 !important"><em>//開始時間</em></span>
        Instant start = Instant.now();

        <span style="color:#880000 !important"><em>//這裡需要一個執行緒池的支援</em></span>
        ForkJoinPool pool = <span style="color:#000088 !important">new</span> ForkJoinPool();

        ForkJoinTask<Long> task = <span style="color:#000088 !important">new</span> ForkJoin(<span style="color:#006666 !important">0</span>L, <span style="color:#006666 !important">10000000000</span>L);
        <span style="color:#880000 !important"><em>// 沒有返回值     pool.execute();</em></span>
        <span style="color:#880000 !important"><em>// 有返回值</em></span>
        long sum = pool.invoke(task);

        <span style="color:#880000 !important"><em>//結束時間</em></span>
        Instant end = Instant.now();
        System.out.println(Duration.between