Java 8 新特性介紹

Java 8 新特性介紹

新特性分類

  1. 語言功能增加特性
  2. API 類庫
  3. 平臺和虛擬機
  4. 周邊工具

語言功能增加特性

  • 函數(shù)式接口
  • lambda表達式
  • 方法引用
  • 接口(interface)的改進

類庫

  • 集合庫的Lambda增強
  • 并行集合操作
  • 流API
  • 日期時間API
  • 網(wǎng)絡
  • 安全
  • IO

JVM和平臺

  • Nashorn JavaScript Engine
  • Reduce Cache Contention on Specified Fields
  • Remove the Permanent Generation
  • Retire Some Rarely-Used GC Combinations
  • Fence Intrinsics
  • Reduce Class Metadata Footprint
  • Enhanced Verification Errors

周邊工具

  • DocTree API
  • DocLint
  • Access to Parameter Names at Runtime
  • Repeating Annotations
  • Enhance javac to Improve Build Speed

新特性介紹

函數(shù)式接口 FunctionalInterface

所謂函數(shù)式接口是只有一個抽象方法的接口
函數(shù)式接口實例 @FunctionalInterface注解
只要接口定義滿足函數(shù)式接口 無論接口是否加上@FunctionalInterface注解 編譯器都認為是函數(shù)式接口

函數(shù)式接口四條規(guī)則

  1. 接口只能定義一個抽象方法
  2. 覆蓋Object類的抽象方法不算抽象方法里
  3. 注解@FunctionalInterface 只能用在接口上
  4. 如果滿足函數(shù)式接口 無論是否使用@FunctionalInterface注解 編譯器都認為是函數(shù)式接口
    JDK一些常用函數(shù)式接口
java.lang.Runnable
java.io.FileFilter
java.io.FilenameFilter
java.util.Comparator
java.util.concurrent.Callable

lambda表達式

冗長無意義的代碼

** 一個簡單的線程例子 **

//使用匿名內(nèi)部類寫一個線程方法
  new Thread(new Runnable() {
   @Override
   public void run() {
    System.out.println(Thread.currentThread().getName());
   }
  }).start();

//小寫轉(zhuǎn)大寫
List<String> nameList = Arrays.asList("a","b","c");
List<String> upperNameList = new ArrayList<String>();
for(String name : nameList){
    upperNameList.add(name.toLowerCase());
}

** 寫代碼能簡單一點嗎?**

可以

        // 使用lambda表達式
        new Thread(
                () -> System.out.println(Thread.currentThread().getName())

        ).start();
        
        
        //使用流操作
        nameList.stream().map(str -> str.toUpperCase());

Lambda表達式一般形式


//求和lambda表達式
(int x, int y) -> {return x + y;}

(String s) -> {System.out.println(s)};

list -> {list.add(42); return list;}

lambda表達式內(nèi)可以訪問外部變量

// Java 8 以前 i 必須用final修飾
int i = 0;
new Thread(new Runnable() {

    @Override
    public void run() {
System.out.println(i);
// i = 1; 都不能對i進行賦值
    }
});

int j = 1;
new Thread(() -> {
    System.out.println(j);
    // j = 1;不能對j進行賦值 官方名稱為"effectively final"
});

** effectively final **

目標類型 target type

lambda表達式是什么?
比如 x -> x * 2 是函數(shù)式接口 interface IntOperation { int operate(int i); }
的一個實例

  IntOperation twice = x -> x * 2;
        IntOperation square = x -> x * x;
        System.out.println(twice.operate(3));
        System.out.println(square.operate(3));

        // lambda必須是函數(shù)式接口實例
        // Object o = x -> System.out.println(x);

        Consumer<?> c = x -> System.out.println(x);
        Object o = c;
作用域和上下文
public class WhatIsThis {

    void checkThis() {
        System.out.println("outer " + this);

        new Thread(new Runnable() {

            public void run() {
                System.out.println("inner " + this);
                printThis();
            }
        }).start();

        new Thread(() -> {
            System.out.println("in lambda " + this);
        }).start();
    }

    void printThis() {
        System.out.println("from printThis() " + this);
    }

    public static void main(String[] args) {
        new WhatIsThis().checkThis();
    }
}

方法引用

編程語言內(nèi)各種方法抽象出來作為一個變量類型迂猴,作為參數(shù)輸入彻况,或者做為返回值返回
通過方法引用實現(xiàn)函數(shù)式編程語言的function as first-classs object(函數(shù)作為一等公民) 方法可以像變量一樣做為參數(shù)或返回值

例子一

 //字符串小寫轉(zhuǎn)大寫 
 Function<String, String> upperfier = String::toUpperCase;
 System.out.println(upperfier.apply("Hello"));

** 例子二 **

  //集合元素判斷
 Set<String> knowNames = new HashSet<>();
 knowNames.add("Zhang");
 knowNames.contains("Zhang");

 Predicate<String> isKnowName = knowNames::contains;
 isKnowName.test("Zhang");
 isKnowName.test("Li");

方法引用類型有
| 類型 | 使用方法 | lambda形式 |
| --- | --- |
| 實例方法 | x::toString | () -> x.toString() |
| 靜態(tài)方法 | String::valueOf | x -> x.toString() |
| 構(gòu)造方法 | ArrayList::new | () -> new ArrayList<>() |
| 數(shù)組構(gòu)造方法 | EleType[]::new |

JDK對方法的的抽象(輸入輸出抽象) 在java.util.function包下

// 輸入類型為T輸出為R
public interface Function<T, R>{
      R apply(T t);
}

//輸出布爾值
public interface Predicate<T>{  
     boolean test(T t);
}

// 沒有輸入 輸出為T
public interface Supplier<T> {
    T get();
}

// 輸入為類型T 沒有輸出
public interface Consumer<T> {
      void accept(T t);
}
   

方法引用與lambda表達式的等價關系

接口的改進

接口允許有實現(xiàn)方法
virtual extension method
default 關鍵字來修飾實現(xiàn)方法

default public  void printOrderInfo(String orderId){
      System.out.println(orderId);
}

接口允許有靜態(tài)方法

public interface InterfaceStaticMethod {
    static void myMethod(){
        System.out.println("myMethod");
    }
}
// Comparator接口生成比較器方法
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
            Function<? super T, ? extends U> keyExtractor)
    {
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
            (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
    }

//根據(jù)名字做比較的比較器
Comparator nameComparator = Comparator.comparing(Employee::getName);

//根據(jù)薪水做比較比較器
Comparator salaryComparator = Comparator.comparing(Employee::getSalary);

接口多繼承問題

  1. 繼承多個具有相同的方法接口 必須在子接口方法里明確指定調(diào)用哪個父接口的方法
  2. 實現(xiàn)接口的類也同理
interface SubInterface extends MyInterface1,MyInferface2{

 @Override
 default void test(String str) {
  MyInferface2.super.test(str);
 }
 
}

class SubClass implements  MyInterface1,MyInferface2{

    @Override
    public void test(String str) {
        MyInterface1.super.test(str);
    }
    
}

類型推導

所謂類型推導編譯器根據(jù)上下文 智能的推斷變量的類型,不需要開發(fā)者顯式指定變量類型

  1. java 7 對范型類型推導改進
 Map<String, Object> map2 = new HashMap<String, Object>();

 // 右邊括號內(nèi)<>參數(shù)類型可以省略 
Map<String, Object> map1 = new HashMap<>();

官方叫做diamond

lambda表達式智能推導參數(shù)類型

Comparator<String> comparator = (String str1,String str2) -> {
   return str1.compareTo(str2);
  };
  
 // 不需要顯式指定str1和str2的類型為String
  Comparator<String> comparator2 = (str1,str2) -> {
   return str1.compareTo(str2);
  };

類型推導上下文范圍

  • Variable declarations
  • Assignments
  • Return statements
  • Array initializers
  • Method or constructor arguments
  • Lambda expression bodies
  • Conditional expressions, ?:
  • Cast expressions

新特性花式組合完法

  1. 比較器的N種寫法
    代碼例子

類庫

集合庫的Lambda增強

  1. Collection新增方法

Iterable.forEach(Consumer)
Iterator.forEachRemaining(Consumer)
Collection.removeIf(Predicate)
Collection.spliterator()
Collection.stream()
Collection.parallelStream()
List.sort(Comparator)
List.replaceAll(UnaryOperator)
Map.forEach(BiConsumer)
Map.replaceAll(BiFunction)
Map.putIfAbsent(K, V)
Map.remove(Object, Object)
Map.replace(K, V, V)
Map.replace(K, V)
Map.computeIfAbsent(K, Function)
Map.computeIfPresent(K, BiFunction)
Map.compute(K, BiFunction)
Map.merge(K, V, BiFunction)
Map.getOrDefault(Object, V)

并行集合操作

集合的塊數(shù)據(jù)操作

流API

** Stream的本質(zhì)是對數(shù)據(jù)源進行抽象 提供一套通用API對數(shù)據(jù)源操作 **

引入Stream谈秫、函數(shù)式接口抚岗、lambda等幾大特性java 8 有了一些函數(shù)式編程語言味道
Stream實現(xiàn)map filter reduce等操作或杠,Stream的數(shù)據(jù)源包括數(shù)組、集合宣蔚、IO通道向抢、隨機數(shù)生成器等,Stream相關接口在java.util.stream包下


public interface Stream<T> extends BaseStream<T, Stream<T>> {
    //過濾 
   Stream<T> filter(Predicate<? super T> predicate);

   // 映射
   <R> Stream<R> map(Function<? super T, ? extends R> mapper);

  //聚合
  T reduce(T identity, BinaryOperator<T> accumulator);
}

Stream接口方法分類

Intermediate 輸出還是stream认境,比如filter,map
Terminal 對流的聚合操作比如 sum count等

對流操作的一般過程
  1. 從數(shù)據(jù)源獲取流
  2. 執(zhí)行一個或多個中間操作
    3 執(zhí)行一個終結(jié)操作(terminal operation)

//對list求和
int result = list.stream().reduce(0,(x,y) -> x + y);

//對list過濾(大于5的數(shù)字)再求和
int result = list.stream().filter(x -> x > 5).reduce(0,(x,y) -> x + y);

//對list 過濾(大于5的數(shù)字) 映射(求平方) 再求和,先通過mapToInt生成IntStream挟鸠,調(diào)用sum方法
result = list.stream().filter(x -> x > 5).map(x -> x * x).mapToInt(x -> x).sum();

各位腦補下寫代碼過程中如果用Stream的map filter reduce來簡化代碼

流的延遲初始化特性lazy

數(shù)字流
IntStream
LongStream
DoubleStream
可以對數(shù)字流進行sum, min, max,average等聚合操作

List<String> strings = Arrays.asList("a", "b", "c");
strings.stream()                    // Stream<String>
       .mapToInt(String::length)    // IntStream
       .longs()                     // LongStream
       .mapToDouble(x -> x / 10.0)  // DoubleStream
       .boxed()                     // Stream<Double>
       .mapToLong(x -> 1L)          // LongStream
       .mapToObj(x -> "")           // Stream<String>

Unix下的管道叉信?

玩轉(zhuǎn)Stream之數(shù)據(jù)庫SQL

https://technology.amis.nl/2013/10/05/java-8-collection-enhancements-leveraging-lambda-expressions-or-how-java-emulates-sql/

http://www.oracle.com/technetwork/articles/java/ma14-java-se-8-streams-2177646.html

流與集合比較

Stream輔助類Collector

日期時間API

新的java.time包

Instant——代表的是時間戳
LocalDate——日期(不帶時間)比如2016-10-29。它可以用來存儲生日艘希,周年紀念日硼身,入職日期等,
LocalTime——它代表的是不含日期的時間
LocalDateTime——它包含了日期及時間覆享,不過還是沒有偏移信息或者說時區(qū)佳遂。
ZonedDateTime——這是一個包含時區(qū)的完整的日期時間,偏移量是以UTC/格林威治時間為基準的撒顿。
枚舉類
DayOfWeek
Month

JAVA 8:健壯丑罪、易用的時間/日期API

網(wǎng)絡

安全

JVM和平臺

周邊工具

----------參考資料-----------------
Oracle 官方 Java8新特性
Open JDK feature list
關于java lambda表達式一切問題

java 8 lambda 方法引用 Stream綜合介紹

lambda和背后invokedynamic

JAVA 8:健壯、易用的時間/日期API

lambda和內(nèi)部類性能比較

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末凤壁,一起剝皮案震驚了整個濱河市吩屹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌客扎,老刑警劉巖祟峦,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異徙鱼,居然都是意外死亡宅楞,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進店門袱吆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來厌衙,“玉大人,你說我怎么就攤上這事绞绒∩粝#” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵蓬衡,是天一觀的道長喻杈。 經(jīng)常有香客問我,道長狰晚,這世上最難降的妖魔是什么筒饰? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮壁晒,結(jié)果婚禮上瓷们,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好谬晕,可當我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布碘裕。 她就那樣靜靜地躺著,像睡著了一般攒钳。 火紅的嫁衣襯著肌膚如雪帮孔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天夕玩,我揣著相機與錄音你弦,去河邊找鬼惊豺。 笑死燎孟,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的尸昧。 我是一名探鬼主播揩页,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼烹俗!你這毒婦竟也來了爆侣?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤幢妄,失蹤者是張志新(化名)和其女友劉穎兔仰,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蕉鸳,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡乎赴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了潮尝。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片榕吼。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖勉失,靈堂內(nèi)的尸體忽然破棺而出羹蚣,到底是詐尸還是另有隱情,我是刑警寧澤乱凿,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布顽素,位于F島的核電站,受9級特大地震影響徒蟆,放射性物質(zhì)發(fā)生泄漏胁出。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一后专、第九天 我趴在偏房一處隱蔽的房頂上張望划鸽。 院中可真熱鬧,春花似錦、人聲如沸裸诽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽丈冬。三九已至嘱函,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間埂蕊,已是汗流浹背往弓。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蓄氧,地道東北人函似。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像喉童,于是被迫代替她去往敵國和親撇寞。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,685評論 2 360

推薦閱讀更多精彩內(nèi)容