jdk1.8 新特性

參考文章: 

https://mp.weixin.qq.com/s?__biz=MzU3NDE0NjMwNw==&mid=2247485581&idx=2&sn=1d16097968ae544c91c5775e7fd835e2&chksm=fd379ae1ca4013f790bbf49a97119374edc6928202a201d535ec65473697c688e9f1c2c2031f&mpshare=1&scene=1&srcid=&sharer_sharetime=1574038151336&sharer_shareid=e1d4a35ff3308c63451b2ff386b1e2bd#rd

https://www.runoob.com/java/java8-streams.html

Java 8 新特性

Java 8 (又稱爲 jdk 1.8) 是 Oracle 公司於 2014 年 3 月 18 日發佈的一個主要版本Java 語言開發的。支持函數式編程新的 JavaScript 引擎,新的日期 API,新的Stream API 等。


新特性

Java8 新增了非常多的特性,我們主要討論以下幾個:

  • Lambda 表達式 − Lambda 允許把函數作爲一個方法的參數

  • Stream API −新添加的Stream API(java.util.stream) 把真正的函數式編程風格引入到Java中。

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

  • Optional 類 − Optional 類已經成爲 Java 8 類庫的一部分,用來解決空指針異常。

  • Date Time API − 加強對日期與時間的處理。

  • 默認方法 − 默認方法就是一個在接口裏面有了一個實現的方法。

  • Nashorn, JavaScript 引擎 − Java 8提供了一個新的Nashorn javascript引擎,它允許我們在JVM上運行特定的javascript應用

Lambda 表達式,也可稱爲閉包,它是推動 Java 8 發佈的最重要新特性,允許把函數作爲一個方法的參數。使用 Lambda 表達式可以使代碼變的更加簡潔緊湊。

語法

lambda 表達式的語法格式如下 parameters爲參數值,expression  爲接口執行結果表達式: 
(parameters) -> expression 或 (parameters) ->{ statements; } 其中parameters不需要聲明參數類型,編譯器可統一識別參數值。

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)

public class Java8Tester {
    public static void main(String args[]){

        List<String> names1 = new ArrayList<String>();
        names1.add("Google ");
        names1.add("Runoob ");
        names1.add("Taobao ");

        List<String> names2 = new ArrayList<String>();
        names2.add("Google ");
        names2.add("Runoob ");
        names2.add("Taobao ");

        System.out.println("使用 Java 7 語法: ");
        Collections.sort(names1, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return s1.compareTo(s2);
            }
        });
        System.out.println(names1);

        System.out.println("使用 Java 8 語法: ");
        //Collections.sort(names,  (s1,s2) -> s1.compareTo(s2) ); 不定義類型也是可以的
        Collections.sort(names2,  (String s1, String s2) -> s1.compareTo(s2) );
        System.out.println(names2);
    }

}
 

方法引用通過方法的名字來指向一個方法。方法引用中::後只是方法名,不能加();  可以使語言的構造更緊湊簡潔,減少冗餘代碼,使用兩對冒號 : :。

list.forEach((s) -> System.out.println(s)); 使用方法引用後變成   list.forEach(Syetem.out::println);

https://www.runoob.com/java/java8-method-references.html

 

 

Java 8 API添加了一個新的抽象稱爲流Stream,可以讓你以一種聲明的方式處理數據,極大提高Java程序員的生產力。
Stream 使用一種類似用 SQL 語句從數據庫查詢數據的直觀方式來提供一種對 Java 集合運算和表達的高階抽象。
這種風格將要處理的元素集合看作一種流, 流在管道中傳輸, 並且可以在管道的節點上進行處理, 比如篩選, 排序,聚合等。
元素流在管道中經過中間操作(intermediate operation)的處理,最後由最終操作(terminal operation)得到前面處理的結果。

什麼是 Stream?

Stream(流)是一個來自數據源的元素隊列並支持聚合操作

  • 元素是特定類型的對象,形成一個隊列。 Java中的Stream並不會存儲元素,而是按需計算。
  • 數據源 流的來源。 可以是集合,數組,I/O channel, 產生器generator 等。
  • 聚合操作 類似SQL語句一樣的操作, 比如filter, map, reduce, find, match, sorted等。

和以前的Collection操作不同, Stream操作還有兩個基礎的特徵:

  • Pipelining: 中間操作都會返回流對象本身。 這樣多個操作可以串聯成一個管道, 如同流式風格(fluent style)。 這樣做可以對操作進行優化, 比如延遲執行(laziness)和短路( short-circuiting)。
  • 內部迭代: 以前對集合遍歷都是通過Iterator或者For-Each的方式, 顯式的在集合外部進行迭代, 這叫做外部迭代。 Stream提供了內部迭代的方式, 通過訪問者模式(Visitor)實現。
List<Integer> transactionsIds = 
widgets.stream()
             .filter(b -> b.getColor() == RED)  //過濾顏色爲紅色
             .sorted((x,y) -> x.getWeight() - y.getWeight()) //通過weight排序
             .mapToInt(Widget::getWeight) //getWeight通過這個方法獲得對應int值
             .sum(); //求總和



List<SysUser> arrayList = new ArrayList<>();
SysUser sysUser1 = new SysUser();
sysUser1.setMailAddr("1");

SysUser sysUser2 = new SysUser();
sysUser2.setMailAddr("");
arrayList.add(sysUser1);
arrayList.add(sysUser2);

List<SysUser> userByRoleId = arrayList.stream().filter(sysUser -> StringUtils.isNotEmpty(sysUser.getMailAddr())).collect(Collectors.toList());

List<String>  mailList = arrayList.stream().filter(sysUser -> StringUtils.isNotEmpty(sysUser.getMailAddr())).map(SysUser::getMailAddr).collect(Collectors.toList());




forEach   Stream 提供了新的方法 'forEach' 來迭代流中的每個數據。以下代碼片段使用 forEach 輸出了10個隨機數

Random random = new Random();
//ints創建的是無限流  通過limit限制個數
random.ints().limit(10).forEach(System.out::println);   //System.out::println   作爲靜態方法來引

map  中間操作map會將元素根據指定的Function接口來依次將元素轉成另外的對象( 將一個流中的值轉換成一個新的流 )

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
// 獲取對應的平方數
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());

List<String> strings = Arrays.asList("Google", "Runoob", "Taobao");
//將元素變大寫 返回List<String> 
List<String> collect = strings.stream().map(s -> s.toUpperCase()).collect(Collectors.toList());

//lamda表達式 return返回值
List<String> collect22 = strings.stream().map(s -> {
    String concat = s.concat(" java");
    return concat;
}).collect(Collectors.toList());

//將元素變大寫 返回Set<String> 
Set<String> collect = strings.stream().map(s -> s.toUpperCase()).collect(Collectors.toCollection(TreeSet::new));

//string轉list<Integer>        
List<Integer> caseIdsArr = Arrays.stream("1,2".split(",")).map(s -> Integer.valueOf(s.trim())).collect(Collectors.toList());
List<Integer> caseIdsArr = Arrays.asList((Integer[]) ConvertUtils.convert("1,2".split(","),Integer.class));

filter 用於通過設置的條件過濾出元素。以下代碼片段使用 filter 方法過濾出空字符串:

 List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl", "2lm");

//獲取數字開頭的元素
List<String> list2 = strings .stream().filter((s) -> Character.isDigit(s.charAt(0))).collect(Collectors.toList());

//集合去除空字符串         //Stream<T> filter(Predicate<? super T> predicate);
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());

//等同於下面的表達式 stream() − 爲集合創建串行流。
List<String> filtered1 = strings.stream().filter(new Predicate<String>() {
    @Override
    public boolean test(String string) {
        return !string.isEmpty();
    }
}).collect(Collectors.toList());

//獲取空字符串的數量
long count = strings.stream().filter(string -> string.isEmpty()).count();
//篩選字符串長度==3的字符串                        string->string.length()==3其實就是test方法的方法體
List<String> filtered1 = strings.stream().filter(string->string.length()==3).collect(Collectors.toList());

@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);
}

limit 用於獲取指定數量的流。 以下代碼片段使用 limit 方法打印出 10 條數據:

Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

sorted 用於對流進行排序。以下代碼片段使用 sorted 方法對輸出的 10 個隨機數進行排序:

random.ints().limit(10).sorted().forEach(System.out::println);

skip:與limit互斥,使用該方法跳過元素

// 跳過前三個元素,從第四個開始輸出
list.stream().skip(3).forEach(user -> System.out.println(user))

stream 流中的分頁操作

一個skip和一個limit,skip代表着要跳過結果集中的前幾個數據,limit也就是取結果集中的幾個數據
stream.skip(2).limit(2).forEach(s -> System.out.println(s));

Collectors   Collectors 類實現了很多歸約操作,例如將流轉換成集合和聚合元素Collectors 可用於返回列表或字符串

List<String> strings = Arrays.asList("abc","","bc","efg","abcd","","jkl");
List<String> filtered = strings.stream().filter(string->!string.isEmpty()).collect(Collectors.toList());
System.out.println("篩選列表: "+filtered);

String mergedString=strings.stream().filter(string->!string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("合併字符串: "+mergedString);

統計    產生統計結果的收集器。它們主要用於int、double、long等基本類型上

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println("列表中最大的數 : " + stats.getMax());
System.out.println("列表中最小的數 : " + stats.getMin());
System.out.println("所有數之和 : " + stats.getSum());
System.out.println("平均數 : " + stats.getAverage());

Optional

private static BigDecimal fetchMallprice(SkuVO skuVO) throws Exception {
    return Optional.ofNullable(skuVO)
            .map(s -> s.getPrice()) //此方法有個判空處理 如果爲null 則直接執行 orElseThrow方法
            .map(p -> p.getMallPrice())
            .filter(m -> m.compareTo(new BigDecimal("10")) == 1) //也有個判空處理
            .orElseThrow(() -> new Exception("skuVO不合法"));
}

//String[]--->Integer[]
String ids =null; List<Integer> collect = Arrays.stream(Optional.ofNullable(ids).orElse("").split(",")) .filter(s -> StringUtils.isNotEmpty(s)) .map(s -> Integer.valueOf(s)).collect(Collectors.toList());

 

Optional是jdk1.8出的新特性,其實思想挺簡單的,就是把實體包裝了一層,包裝的時候,如果是實體爲空,則返回一個空的Optional,否則返回Optional。

Optional.ofNullable(skuVO)首先構造一個Optional,map(Function<? super T, ? extends U> mapper)接收一個Funtion,filter過濾map返回的值,最後通過orElseThrow拋出異常。

 

https://www.cnblogs.com/kobelieve/p/11265651.html
https://blog.csdn.net/zknxx/article/details/78586799

 

 

 

 

 

 

 

 

 

發佈了63 篇原創文章 · 獲贊 22 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章