Java8新特性總結(jié)

一.接口內(nèi)允許添加默認(rèn)實(shí)現(xiàn)的方法

在原來(lái)的定義中接口中只能有方法聲明懊直,不能有方法體。在Java8中,接口也可以有自己帶有實(shí)現(xiàn)的方法啦。具體來(lái)說(shuō)是要用default來(lái)修飾的方法喳魏,其可以像類中的方法一樣有執(zhí)行語(yǔ)句。在實(shí)現(xiàn)接口時(shí)怀薛,可以不實(shí)現(xiàn)其default方法刺彩,并且實(shí)現(xiàn)類對(duì)象可以調(diào)用其接口的default方法。當(dāng)然也可以在實(shí)現(xiàn)類中覆蓋default方法枝恋。

public class InterfaceDemo {
    public static void main(String[] args) {
        Formula formula = new Formula() {
            @Override
            public double calculate(int a) {
                return a + 1;
            }

//           @Override
//            public double sqrt(int a) {
//              return a;
//            }
        };

        System.out.println(formula.calculate(100));
        System.out.println(formula.sqrt(100));
    }
}

interface Formula {
    //計(jì)算
    double calculate(int a);

    //求平方根
    default double sqrt(int a) {
        return Math.sqrt(a);
    }
}

二.Lambda表達(dá)式

Lambda簡(jiǎn)化了匿名內(nèi)部類的寫(xiě)法创倔。Java8中可以通過(guò)類型推斷來(lái)判斷出用戶的意圖,不必將類型等信息寫(xiě)全焚碌。特別是方法實(shí)現(xiàn)體中只有一句語(yǔ)句的實(shí)現(xiàn)類畦攘,更能加大簡(jiǎn)化力度。

Lambda解決了將一個(gè)方法作為參數(shù)傳值的問(wèn)題十电。解決了一個(gè)函數(shù)是否可以獨(dú)立存在的問(wèn)題念搬。是Java向函數(shù)式編程的一種靠攏。

一般在某個(gè)方法只使用一次的地方使用Lambda表達(dá)式摆出;如果方法沒(méi)有入?yún)ⅲ瑒t只寫(xiě)一個(gè)()->{語(yǔ)句}首妖;當(dāng)只有一個(gè)參數(shù)偎漫,且類型可推斷時(shí),()可省略有缆;如果方法體中只有一條語(yǔ)句花括號(hào)可以省略象踊;


public class LambdaDemo {
    public static void func1() {
        System.out.println("not use Lambda");
        List<String> strs = Arrays.asList("hello","word","apple","people","sea","book","school","computer");

        //old way 
        Collections.sort(strs,new Comparator<String>() {
            @Override
            public int compare(String a,String b) {
                return b.compareTo(a);
            }
        });

        System.out.println(strs);
    }

    public static void func2() {
        System.out.println("use Lambda");
        List<String> strs = Arrays.asList("hello","word","apple","people","sea","book","school","computer");

        //way 1
        Collections.sort(strs,(String a,String b) -> {
            return a.compareTo(b);
        });

        //way 2 : only one statement 
        Collections.sort(strs,(String a,String b) -> a.compareTo(b));

        //way 3 : omit class
        Collections.sort(strs,(a,b) -> a.compareTo(b));

        System.out.println(strs);
    }
}

三.函數(shù)式接口Functional Interface

學(xué)習(xí)了上述Lambda的內(nèi)容肯定會(huì)有一些疑問(wèn):如果接口有多個(gè)需要實(shí)現(xiàn)的方法 呢,還能使用Lambda棚壁?如果可以的話Lambda是如何做推斷的杯矩。

答案是,使用Lambda時(shí)要求接口中只能有一個(gè)抽象方法(通過(guò)default修飾的帶有方法體的接口中的方法不是抽象方法)袖外。

如果一個(gè)接口被注解@FunctionalInterface修飾史隆,則該接口只能有一個(gè)抽象方法,否則會(huì)報(bào)錯(cuò)曼验。

四.引用類的構(gòu)造器及方法

在Lambda中若是直接調(diào)用了一個(gè)方法泌射,且調(diào)用方法的形參和要實(shí)現(xiàn)的接口抽象方法形參一致粘姜,則可以進(jìn)一步簡(jiǎn)寫(xiě)。舉例如下:
接口定義:

@FunctionalInterface
interface Converter<F,T> {
    T convert(F form);
}

Lambda表達(dá)式

//舊的寫(xiě)法
Converter<String,Integer> convert1 = (from) -> Integer.valueOf(from);
//新的寫(xiě)法
Converter<String,Integer> convert2 = Integer::valueOf;

System.out.println(convert1.convert("1234"));

引用其他類型的方法

  • 例子中的方法是Integer類的靜態(tài)方法熔酷,如果是某個(gè)類的實(shí)例方法孤紧,則應(yīng)該使用一個(gè)對(duì)象加::來(lái)引用。如拒秘,obj::func;
  • 如果要調(diào)用的一個(gè)構(gòu)造方法(抽象方法返回的是一個(gè)對(duì)象)号显,則應(yīng)該這樣使用:Integer::new。用new代替構(gòu)造方法名字躺酒。

五.Lambda訪問(wèn)外部變量及接口默認(rèn)方法

訪問(wèn)局部變量

  • 可以訪問(wèn)局部的final變量押蚤,但不能修改。
  • 與匿名內(nèi)部類不同的是阴颖,外部變量不需要顯示地聲明為final活喊,但卻要有final的特點(diǎn),不能被修改量愧,在Lambda之后被修改也不行钾菊。

訪問(wèn)成員變量和靜態(tài)變量
可以任意讀寫(xiě),舉例如下:

public class FunctionInterface {
    String str = "init";
    static Integer num = 0;

    public void testScope() {
        Converter<String,Integer> convert = (from) -> {
            //在這里可訪問(wèn)成員變量和靜態(tài)變量
            str = from;
            num = Integer.valueOf(from);
            return num;
        };

        System.out.println(convert.convert("3453"));
        System.out.println(convert.convert("5678"));
    }        
}

訪問(wèn)接口的默認(rèn)方法
在匿名類中可以訪問(wèn)接口定義的默認(rèn)方法偎肃,在Lambda中不可以訪問(wèn)煞烫。

六.內(nèi)置函數(shù)式接口

Java8中內(nèi)置了許多函數(shù)式接口,包括Comparator和Runnable等累颂,它們被添加了@FunctionalInterface注解滞详,以用來(lái)支持Lambda表達(dá)式。

6.1Predicate斷言

查看源碼紊馏,這個(gè)函數(shù)式接口中要實(shí)現(xiàn)的方法為:boolean test(T t); 即一個(gè)判斷傳入值真假的方法料饥,當(dāng)然判斷的規(guī)則由你自己定義。
如定義一個(gè)判斷字符串長(zhǎng)度是否大于10的Predicate:

import java.util.function.Predicate;

public class PredicateDemo {
    public static void main(String[] args) {
        Predicate<String> predicate = s -> s.length() > 10;

        System.out.println(predicate.test("hello"));
        System.out.println(predicate.test("hello,world!"));
    }
}

6.2 Function

查其源碼朱监,需要實(shí)現(xiàn)一個(gè)R apply(T t)的方法岸啡。這個(gè)接口提供鏈?zhǔn)秸{(diào)用、組合的功能赫编。

6.3 Supplier

Supplier<Person> personSupplier = Person::new;
personSupplier.get();

6.4 Consumer

??
Consumer<Person> greeter = (p) -> System.out.println("Hello, " + p.firstName);
greeter.accept(new Person("Luke", "Skywalker"));

6.5 Optional

參考資料

七.Stream流

什么是Stream流巡蘸?
參考資料
Stream流提供了一種對(duì)集合Collection的方便的操作。分為“中間操作”和“終端操作”兩種擂送。中間操作的結(jié)果還是返回一個(gè)Stream悦荒,可以繼續(xù)操作;而終端操作會(huì)返回一個(gè)結(jié)構(gòu)不能繼續(xù)流操作了嘹吨。

要使用Sream首先要通過(guò)Collection的Stream方法獲取一個(gè)Stream對(duì)象搬味。

7.1 Filter過(guò)濾 中間操作

篩選出集合中滿足一定條件的元素。Stream有一個(gè)filter方法,入?yún)⑹且粋€(gè)Predicate身腻,篩選結(jié)果是Predicate.test為true的集合的Stream产还。下面來(lái)看一個(gè)篩選出String集合中以"s"開(kāi)頭的String的程序:

List<String> list = Arrays.asList("hello","world","apple","people","sea",
                                  "watch","table","book","school","help");
list
    .stream() //獲取stream
    .filter(s -> s.startsWith("s"))  //設(shè)置filter。中間操作
    .forEach(System.out::println);   //打印出流中的元素嘀趟。終端操作

7.2 Sorted排序 中間操作

可以給sorted()方法傳入一個(gè)Comparator用來(lái)自定義排序脐区,否則將使用默認(rèn)排序規(guī)則。

list
    .stream()
    .sorted((a,b) -> b.compareTo(a))
    .forEach(System.out::println);

7.3 Map

map方法入?yún)橐粋€(gè)Function函數(shù)式接口她按。調(diào)用map方法將對(duì)集合中的每一個(gè)元素執(zhí)行一下Function中的apply方法牛隅,并返回由其返回值組成的集合的流。

舉例:將表示數(shù)字的字符串集合全部轉(zhuǎn)換為數(shù)字再加一后輸出酌泰。

List<String> list = Arrays.asList("10","100","1000");

System.out.println("---- test map ----");
list
    .stream()
    .map(Integer::valueOf)  //轉(zhuǎn)換為整數(shù)
    .map(a -> a + 1)        //執(zhí)行加一操作
    .forEach(System.out::println);

7.4Match匹配

是種終端操作媒佣,結(jié)果不是stream對(duì)象,而是boolean值
根據(jù)Predicate指定的規(guī)則判斷集合中是否有匹配的陵刹,有的話返回true默伍。
有三種形式,anyMatch:有一個(gè)匹配就返回true衰琐。allMatch:全部匹配返回true也糊。noneMatch:全部不匹配返回true。

boolean anyMatch(Predicate<? super T> predicate);
boolean allMatch(Predicate<? super T> predicate);
boolean noneMatch(Predicate<? super T> predicate);

7.5 Count計(jì)數(shù)

終端操作羡宙,統(tǒng)計(jì)stream中元素的個(gè)數(shù)狸剃。

long count = 
    list
        .stream() //獲取stream
        .filter(s -> s.startsWith("s"))  //設(shè)置filter。中間操作
        .count();

7.6 Reduce

list[0]和list[1]執(zhí)行操作狗热,得到的結(jié)果為result钞馁。result再和list[2]執(zhí)行操作,得到的結(jié)果result匿刮。依次進(jìn)行僧凰,對(duì)所有元素執(zhí)行一遍。

根據(jù)上述描述也可以看出熟丸,這里的“操作”必須滿足兩個(gè)入?yún)⒀荡搿⒎祷刂凳峭活愋偷摹?/p>

reduce方法的入?yún)⑹牵?strong>BinaryOperator<T> 這里的T就是集合的元素類型。

舉例:求Integer集合中所有元素的和虑啤。

List<Integer> list = Arrays.asList(1,2,3,4,5);

System.out.println("---- test reduce ----");
Optional<Integer> sum = 
    list
        .stream()
        .reduce((a,b) -> a + b);

sum.ifPresent(System.out::println);

注意:reduce的返回值為Optional<T>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末架馋,一起剝皮案震驚了整個(gè)濱河市狞山,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌叉寂,老刑警劉巖萍启,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡勘纯,警方通過(guò)查閱死者的電腦和手機(jī)局服,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)驳遵,“玉大人淫奔,你說(shuō)我怎么就攤上這事〉探幔” “怎么了唆迁?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)竞穷。 經(jīng)常有香客問(wèn)我唐责,道長(zhǎng),這世上最難降的妖魔是什么瘾带? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任鼠哥,我火速辦了婚禮,結(jié)果婚禮上看政,老公的妹妹穿的比我還像新娘朴恳。我一直安慰自己,他們只是感情好帽衙,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布菜皂。 她就那樣靜靜地躺著,像睡著了一般厉萝。 火紅的嫁衣襯著肌膚如雪恍飘。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,482評(píng)論 1 302
  • 那天谴垫,我揣著相機(jī)與錄音章母,去河邊找鬼。 笑死翩剪,一個(gè)胖子當(dāng)著我的面吹牛乳怎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播前弯,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼蚪缀,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了恕出?” 一聲冷哼從身側(cè)響起询枚,我...
    開(kāi)封第一講書(shū)人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎浙巫,沒(méi)想到半個(gè)月后金蜀,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體刷后,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年渊抄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了尝胆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡护桦,死狀恐怖含衔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嘶炭,我是刑警寧澤抱慌,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站眨猎,受9級(jí)特大地震影響抑进,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜睡陪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一寺渗、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧兰迫,春花似錦信殊、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至据德,卻和暖如春鳄乏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背棘利。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工橱野, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人善玫。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓水援,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親茅郎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蜗元,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

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