java8之Lambda知識回顧

前提

18年第一篇文章,祝各位新年快樂哈~

介紹Lambda之前,可以看下我們定義View點擊事件的一般做法

  1. new View(this).setOnClickListener(new View.OnClickListener() {
  2.          @Override
  3.         public void onClick(View view) {
  4.              //...
  5.          }
  6.      });

這種回調模式在日常開發(fā)中很常見,但是隨之也暴露了一些不良的弊端
1、非抽象化晾虑,整個代碼有五行,其實實際邏輯只有在onclick里面仅叫,其他并不關心
2、無法使用外部非final屬性(這個遇到最多了)
3糙捺、this指針意義不明確
4诫咱、等等

所以,java8特性Lambda正好解決了這一系列問題洪灯,以下

new View(this).setOnClickListener(view->{
            //.. doing
        });

1.引入的lambda

lambda是在java8引入的函數表達式坎缭,其實是一種匿名的表達方式,Lambda表達式語法由參數列表签钩、->函數體組成掏呼。函數體既可以是一個表達式也可以是一個代碼塊。
例如以下

 # 表達式
()->8; // 這里8是return的返回結果铅檩,簡化了return
#代碼塊
()->{
  //... 函數體
}

2.案例

說多不如做多憎夷,現(xiàn)在舉個??

2.1 線程利用lambada表達式
new Thread(()->{
            //這里是線程運行的區(qū)域,實質是抽象化了Runnable的run方法
            Log.i(TAG,"Thread is running...");
}).run();
2.2 多種情況利用lambada表達式

首先定義一個測試回調接口類

/**
     * 這個類完全提供一些接口測試
     */
    static class LambdaProvider{

        TestInterface0 mTestInterface0; // 測試不帶參數與不帶返回值
        TestInterface1 mTestInterface1;// 測試帶返回值
        TestInterface2 mTestInterface2;// 測試待返回值昧旨、帶參數
        TestInterface3 mTestInterface3;//測試拋出異常方法

        public void setmTestInterface0(TestInterface0 mTestInterface0) {
            this.mTestInterface0 = mTestInterface0;
        }

        public void setmTestInterface1(TestInterface1 mTestInterface1) {
            this.mTestInterface1 = mTestInterface1;
        }

        public void setmTestInterface2(TestInterface2 mTestInterface2) {
            this.mTestInterface2 = mTestInterface2;
        }

        public void setmTestInterface3(TestInterface3 mTestInterface3) {
            this.mTestInterface3 = mTestInterface3;
        }

        public interface TestInterface0{
            // 不帶參數拾给、不帶返回值
            public void method();
        }

        public interface TestInterface1{
            // 帶返回值
            public int method1();
        }

        public interface TestInterface2{
            // 帶參數
            public int method2(int x);
        }

        public interface TestInterface3{
            // 拋出異常方法
            public void method3() throws Exception;
        }

    }

測試代碼

        String value="";
        LambdaProvider mLambdaProvider = new LambdaProvider();
        mLambdaProvider.setmTestInterface1(()->2); // 直接返回2
        mLambdaProvider.setmTestInterface1(()-> 2+4 ); // 直接返回計算表達式
        mLambdaProvider.setmTestInterface1(()->{ // 直接返回作用域
            Log.i(TAG,"setmTestInterface1 here...");
            //... do something
            String str = value; // 不用final就可以訪問到了
            this.demo(); // this指針不再模糊
            return 3;
        });

        // # 3 針對參數+返回值利用lambada表達式
        mLambdaProvider.setmTestInterface2((x)->2); // 直接返回2
        mLambdaProvider.setmTestInterface2((x)-> 2+4 ); //x 直接返回計算表達式
        mLambdaProvider.setmTestInterface2((x)->{ // 使用形參x計算后返回
            return x+2+4;
        });

        // #4 針對會拋出異常
        mLambdaProvider.setmTestInterface3(()->{
            throw new IllegalStateException("hi~");
        });

3.高效的 Stream api

如果應用最小支持sdk24以上,Stream是非常高效的事情兔沃。當然國內sdk24以上的并不是占絕大多數蒋得,但是我們也可以先了解高效的Stream。
先小試牛刀,一般foreach遍歷list乒疏,我們一般會這么做

        List<String> listSteam = Arrays.asList("0","1","2");
        for (String i:listSteam){
            //...
        }

利用steam api额衙,我們可以這么做

       listSteam.forEach(i->{
            //...
        });

反正我是佩服的??

什么是Stream?

借鑒某大神的說明,“Stream不是集合元素窍侧,它也不是數據結構追驴、不能保存數據,它更像一個更高級的Interator疏之。Stream提供了強大的數據集合操作功能殿雪,并被深入整合到現(xiàn)有的集合類和其它的JDK類型中。流的操作可以被組合成流水線(Pipeline)”

使用Stream可以做很多事情锋爪,如果以后會接觸到rxjava,你會發(fā)現(xiàn)很多操作符是借鑒了Stream里面流的概念丙曙。在Stream操作中,都會涉及一個步驟

上流(Stream)->處理->下流結果(Stream)

舉個例子??
首先創(chuàng)建一個測試model其骄,并且實例了一個數組

class Model{
            public String type;//"1","2" 用于區(qū)別類型
            public String name;
            public Model(String type, String name) {
                this.type = type;
                this.name = name;
            }

            @Override
            public String toString() {
                return "Model (type: " + type +" name: "+name+")";
            }
        }

 List<LambdaProvider.Model> listSteam = Arrays.asList(new LambdaProvider.Model("1","siven0"),
                new LambdaProvider.Model("2","siven1"),new LambdaProvider.Model("2","siven2")
                ,new LambdaProvider.Model("2","siven3"));

場景1:

只提取type是2的數據到新數組

  List<LambdaProvider.Model> newList = listSteam.stream()
                                                .filter(s->s.type.equals("2"))
                                                .collect(Collectors.toList());
  newList.forEach(s-> consoleInput(TAG,"stream newList: "+s));

Collectors是負責接收上面?zhèn)鬟f過來的流亏镰,tolist是將傳遞過來的流重新組合成list
filter是負責過濾上面?zhèn)鬟f過來的流,里面return是一個布爾值

場景2:

提取ype是2的數據拯爽,并且將流轉化為其他數據的流后組成新的數組

List<String> listIndex = listSteam.stream()
                                  .filter(s->s.type.equals("2"))
                                  .map(s->s.name)
                                  .collect(Collectors.toList());
        listIndex.stream().forEach(s-> consoleInput(TAG,"stream listIndex: "+s));

map組要做流轉化索抓,上面的場景是接收到Model的流后,通過訪問實體的對象name轉化為字符串流(下面用map我會貼更加詳細的說明)

map的各種玩法(建議閱讀):

        // 玩玩map轉化
        List<String> stringList = Arrays.asList("1","2","3"); // 隨便申請一個list

        consoleInput(TAG,"玩玩map轉化 ----- flatmap ");
        List<String> tmp0  =  stringList.stream()
                .flatMap((s)->{
                    String str = (String) s + " - 轉化(flatmap)";
                    consoleInput(TAG,"轉化前 "+s + "毯炮,轉化后 " + str);
                    List<String> result = new ArrayList<>();
                    result.add(str);
                    return result.stream();
                })
//                  為了方便讀者閱讀逼肯,我用非lambda表達式
//                  .flatMap(new Function<String, Stream<String>>() {
//                      @Override
//                      public Stream<String> apply(String s) {
//                          String str = (String) s + " - 轉化";
//                          consoleInput(TAG,"轉化前 "+s + "轉化后 " + str);
//                          List<String> result = new ArrayList<>();
//                          result.add(str);
//                          return result.stream();
//                      }
//                  })
                .collect(Collectors.toList());// 流收集起來
        consoleInput(TAG,"轉換后結果輸出 ");
        tmp0.stream().forEach(c->consoleInput(TAG,"-> "+c));

        consoleInput(TAG,"玩玩map轉化 ----- map ");
        tmp0 = stringList.stream()
                .map((s)->{
                    String str = (String) s + " - 轉化(map)";
                    consoleInput(TAG,"轉化前 "+s + ",轉化后 " + str);
                    return str;
                })
//                  為了方便讀者閱讀桃煎,我用非lambda表達式
//                .map(new Function<String, String>() {
//                    @Override
//                    public String apply(String s) {
//                        String str = (String) s + " - 轉化(map)";
//                        consoleInput(TAG,"轉化前 "+s + "篮幢,轉化后 " + str);
//                        return str;                    }
//                })
                .collect(Collectors.toList());// 收集
        consoleInput(TAG,"轉換后結果輸出 ");
        tmp0.stream().forEach(c->consoleInput(TAG,"-> "+c));

        consoleInput(TAG,"玩玩map轉化 ----- sum ");
        int sum = stringList.stream()
                .mapToInt(s->Integer.valueOf(s)) // map轉int
                .sorted() // 排序
                .sum();
        consoleInput(TAG,"轉換后結果輸出 "+sum);

這里要思考的就是flatMap與map有什么區(qū)別了,從方法看flatMap是object->stream<T>为迈。而map是object->object三椿。如果你的場景是希望自己的上流傳遞有多次處理邏輯,并不希望馬上得到下流的結果葫辐。那flatMap更滿足你需求了搜锰。如果是直接A到B,明確的結果耿战,map也許更適合你

4.總結

年終了~祝大家工作順利蛋叼,事業(yè)進步!
by siven

2018.1.5

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末昆箕,一起剝皮案震驚了整個濱河市鸦列,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌鹏倘,老刑警劉巖薯嗤,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異纤泵,居然都是意外死亡骆姐,警方通過查閱死者的電腦和手機镜粤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來玻褪,“玉大人肉渴,你說我怎么就攤上這事〈洌” “怎么了同规?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長窟社。 經常有香客問我券勺,道長,這世上最難降的妖魔是什么灿里? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任关炼,我火速辦了婚禮,結果婚禮上匣吊,老公的妹妹穿的比我還像新娘儒拂。我一直安慰自己,他們只是感情好色鸳,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布社痛。 她就那樣靜靜地躺著,像睡著了一般缕碎。 火紅的嫁衣襯著肌膚如雪褥影。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天咏雌,我揣著相機與錄音,去河邊找鬼校焦。 笑死赊抖,一個胖子當著我的面吹牛,可吹牛的內容都是我干的寨典。 我是一名探鬼主播氛雪,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼耸成!你這毒婦竟也來了报亩?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤井氢,失蹤者是張志新(化名)和其女友劉穎弦追,沒想到半個月后,有當地人在樹林里發(fā)現(xiàn)了一具尸體花竞,經...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡劲件,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片零远。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡苗分,死狀恐怖,靈堂內的尸體忽然破棺而出牵辣,到底是詐尸還是另有隱情摔癣,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布纬向,位于F島的核電站择浊,受9級特大地震影響,放射性物質發(fā)生泄漏罢猪。R本人自食惡果不足惜近她,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望膳帕。 院中可真熱鬧粘捎,春花似錦、人聲如沸危彩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽汤徽。三九已至娩缰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間谒府,已是汗流浹背拼坎。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留完疫,地道東北人泰鸡。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像壳鹤,于是被迫代替她去往敵國和親盛龄。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理芳誓,服務發(fā)現(xiàn)余舶,斷路器,智...
    卡卡羅2017閱讀 134,659評論 18 139
  • Java8 in action 沒有共享的可變數據锹淌,將方法和函數即代碼傳遞給其他方法的能力就是我們平常所說的函數式...
    鐵牛很鐵閱讀 1,233評論 1 2
  • 第一章 為什么要關心Java 8 使用Stream庫來選擇最佳低級執(zhí)行機制可以避免使用Synchronized(同...
    謝隨安閱讀 1,491評論 0 4
  • Streams 原文鏈接: Streams 原文作者: shekhargulati 譯者: leege100 狀態(tài)...
    忽來閱讀 5,525評論 3 32
  • 原文地址: http://cr.openjdk.java.net/~briangoetz/lambda/lambd...
    mualex閱讀 631評論 0 0