Lambda結(jié)合函數(shù)式接口的使用

函數(shù)式接口, 一般可以作為方法的參數(shù)和返回值類型

  • 案例1:函數(shù)式接口作為方法的參數(shù)
#自定義函數(shù)式接口
package FunctionInterface;
public interface MyFunctionInterface {
    public abstract void method();
}
public class functionDemo {
    public static void show(MyFunctionInterface myFunctionInterface) {
        myFunctionInterface.method();
    }

public static void main(String[] args) {
     // 方式1
    // 調(diào)用show方法,參數(shù)是一個接口肥惭,可以傳遞接口的匿名內(nèi)部類
        show(new MyFunctionInterface(){
            @Override
            public void method() {
                System.out.println("使用匿名內(nèi)部類重寫抽象方法");
            }
        });

        // 方式2
       // Lambda表達(dá)式
        show(() ->{
            System.out.println("Lambda表達(dá)式實(shí)現(xiàn)");
        });
}
  • 函數(shù)式接口作為參數(shù)
public class functionDemo {
      public static void threadStart(Runnable run) {
        new Thread(run).start();
    }

    // 方式1:匿名內(nèi)部類
  threadStart(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "啟動了");
            }
        });
    // 注意:參數(shù)Runnabl 一個函數(shù)式接口窃植,并且只有一個抽象方法(run),可以傳遞Lambda表達(dá)式
    //方式2: Lambda表達(dá)式
    threadStart(() -> System.out.println(Thread.currentThread().getName() + "啟動了"));
}

輸出:

Thread-0啟動了
Thread-1啟動了
  • 案例2:函數(shù)式接口作為返回值
# 對字符串按照字符長度倒序

package FunctionInterface;
import java.util.Arrays;
import java.util.Comparator;

public class LambdaReturn {
    public static Comparator<String> getComparator(){
        //方式1:方法的返回值類型是一個接口鹤树,我們可以返回這個接口的匿名內(nèi)部類
/*
        return new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                // 按照字符串的降序排列
                return o2.length() - o1.length();
            }
        };
*/
  
        // 方式1: Lambda表達(dá)式
        return (String o1, String o2) -> {
            // 按照字符串的降序排列
            return o2.length() - o1.length();
        };

        // Lambda優(yōu)化
        // return (o1, o2) -> o2.length() - o1.length();
  }

 public static void main(String[] args) {
        // 函數(shù)式接口作為返回值
        String[] strList = {"abc", "bcd", "wudy", "petwr", "world"};
        System.out.println("排序前=" + Arrays.toString(strList));
        Arrays.sort(strList, getComparator());
        System.out.println("排序后=" + Arrays.toString(strList));
    }
}

輸出:

排序前=[abc, bcd, wudy, petwr, world]
排序后=[petwr, world, wudy, abc, bcd]
  • 案例3: Lambda延遲執(zhí)行
  • 有些場景的代碼執(zhí)行后驹针,結(jié)果一定會被使用吃溅,從而造成性能浪費(fèi)风罩,而Lambda是延遲執(zhí)行的陨亡,正好可以作為解決方案
    性能浪費(fèi)的日志案例:對日志消息進(jìn)行拼接后,在滿足條件的情況下進(jìn)行打印輸出
package FunctionInterface;

public class LambdaDelay {
    public static void main(String[] args) {
        String msg1 = "hello";
        String msg2 = "world";
        String msg3 = "java";
        showLog(2, msg1 + msg2 + msg3);
    }

    public static void showLog(int level, String msg) {
        if (level == 1) {
            System.out.println("日志級別等于1" + msg);
        }
    }

注意: 上述代碼存在的問題: 拼接的字符串在level != 1 的時候并沒有用到辛慰,存在性能浪費(fèi)

  • 優(yōu)化如下:
  • 使用Lambda優(yōu)化日志案例
    特點(diǎn):延時加載, 定義一個顯式日志的方法区匠,方法的參數(shù)傳遞日志的等級和MessageBuilder接口
    使用Lambda表達(dá)式作為參數(shù)傳遞,僅僅是把參數(shù)傳遞到showLog方法中
    只有滿足條件(日志等級是1)帅腌,才會調(diào)用接口MessageBuilder中的方法messageBuilder
    如果不滿足條件驰弄,日志的等級不是1,那么接口MessageBuilder中的方法messageBuilder不會執(zhí)行
    所以拼接字符串的代碼也不會執(zhí)行所以不會存在性能的浪費(fèi)
package FunctionInterface;
@FunctionalInterface
public interface MessageBuilder {
    // 定義一個拼接消息的抽象方法, 返回被拼接的消息
    public abstract String builderMessage();
}
package FunctionInterface;

public class LambdaDelay {
    public static void main(String[] args) {
        String msg1 = "hello";
        String msg2 = "world";
        String msg3 = "java";
        showLog(1, () -> {
            return msg1 + msg2 + msg3;
        });
    }

   private static void showLog2(int level, MessageBuilder messageBuilder) {
        if (1 == level) {
            System.out.println("測試啥時候進(jìn)來這里啊!");
            System.out.println(messageBuilder.builderMessage());;
        }
    }

結(jié)論: 當(dāng)level==2的時候速客,不會進(jìn)入Lambda表達(dá)式中戚篙,就不會執(zhí)行字符串拼接,從而節(jié)省性能

  • 案例4: 使用Supplier接口作為方法參數(shù)類型
Supplier 被稱之為生產(chǎn)型接口挽封,指定接口的范型是什么類型已球,那么接口中的get方法就會生產(chǎn)什么類型的數(shù)據(jù)
package FunctionInterface;

import java.util.function.Supplier;
public class SupplierDemo {
    public static void main(String[] args) {
       // 調(diào)用getSupplier方法, 方法的參數(shù)Supplier是一個函數(shù)式接口辅愿,所以可以傳遞Lambda表達(dá)式
       String name = getSupplier(() -> {
               return "wudy";
       });

      //String name = getSupplier(() -> "wudy");
      System.out.println(name);
    }

      public static String getSupplier(Supplier<String> supplier) {
           return supplier.get();
    }
}

輸出:

wudy
  • Supplier接口作為方法參數(shù)類型, 通過Lambda表達(dá)式求出int數(shù)組中的最大值
package FunctionInterface;

import java.util.function.Supplier;
public class SupplierDemo {
    public static void main(String[] args) {
         Integer[] list = {88, 10, -12, -34, 0, 65, 102};
         int maxValue = getMax(() -> {
             System.out.println("second");
              int max = list[0];
              for (int i: list) {
                  if (i > max) {
                      max = i;
                  }
              }
              return max;
        });

        System.out.println(maxValue);
  }

    public static Integer getMax(Supplier<Integer> supplier) {
        System.out.println("first");
        return supplier.get();
    }
}

輸出:

first
second
102
Consumer接口是一個消費(fèi)型接口智亮,范型指定什么類型,就可以使用accept方法消費(fèi)什么類型的數(shù)據(jù)
  • 案例5: Consumer反轉(zhuǎn)字符串
package FunctionInterface;

import java.util.function.Consumer;
public class ConsumerDemo {
    public static void main(String[] args) {
        method("wudy", (String name) -> {
            // 重寫accept
            // 反轉(zhuǎn)字符串
            String revName = new StringBuffer(name).reverse().toString();
            System.out.println(revName);
        });
    }

      public static void method(String name, Consumer<String> consumer){
            consumer.accept(name);
    }
}

輸出:

yduw
  • AndThen方法: 需要兩個Consumer接口点待,可以把兩個Consumer接口組合到一起阔蛉,再對數(shù)據(jù)進(jìn)行消費(fèi)
package FunctionInterface;
import java.util.function.Consumer;

public class ConsumerAndThen {
    public static void main(String[] args) {
        method("Hello World", (String name) -> {
            System.out.println("執(zhí)行con1=" + name.toUpperCase());
        }, (String name) -> {
            System.out.println("執(zhí)行con2=" + name.toLowerCase());
        });
    }

      public static void method(String s, Consumer<String> con1, Consumer<String> con2){
          // 先執(zhí)行con2消費(fèi)數(shù)據(jù),再執(zhí)行con1消費(fèi)數(shù)據(jù)
          con2.andThen(con1).accept(s);
    }
}

輸出:

執(zhí)行con2=hello world
執(zhí)行con1=HELLO WORLD
  • AndThen方法: 格式化打印信息
  • 將下面的字符串按照格式"姓名:XX癞埠。性別:XX" 的格式打印出來状原,要求將打印姓名的動作作為第一個Consumer接口的Lambda實(shí)例,
    將打印性別的動作作為第二個Consumer接口的Lambda實(shí)例苗踪,將兩個Consumer接口按照順序拼接到一起
package FunctionInterface;
import java.util.function.Consumer;

public class FormatPrint {

    public static void main(String[] args) {
        String[] strList = {"wudy,男","peter,女","timo,女"};

        for (String str: strList) {
            printInfo(str, (String name) -> {
                name = str.split(",")[0];
                System.out.print("姓名:" + name);
            }, (String sex) -> {
                sex = str.split(",")[1];
                System.out.println("颠区。性別:" + sex + "。");
            });
        }
    }

    public static void printInfo(String str, Consumer<String> con1, Consumer<String> con2) {
        con1.andThen(con2).accept(str);
    }
}

輸出:

姓名:wudy通铲。性別:男毕莱。
姓名:peter。性別:女颅夺。
姓名:timo朋截。性別:女。
  • 有時候我們需要對某種類型的數(shù)據(jù)進(jìn)行判斷吧黄,從而得到一個boolean值結(jié)果
package FunctionInterface;
import java.util.function.Predicate;

public class PredicateDemo {
    public static void main(String[] args) {
        String str = "macBookPro";
        boolean b = checkString(str, (String s) -> s.length() >15);

        System.out.println(b);
    }

    public static boolean checkString(String str, Predicate<String> predicate) {
        return predicate.test(str);
    }
}

輸出:

false
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末部服,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子拗慨,更是在濱河造成了極大的恐慌廓八,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赵抢,死亡現(xiàn)場離奇詭異瘫想,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)昌讲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進(jìn)店門国夜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人短绸,你說我怎么就攤上這事车吹。” “怎么了醋闭?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵窄驹,是天一觀的道長。 經(jīng)常有香客問我证逻,道長乐埠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮丈咐,結(jié)果婚禮上瑞眼,老公的妹妹穿的比我還像新娘。我一直安慰自己棵逊,他們只是感情好伤疙,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著辆影,像睡著了一般徒像。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蛙讥,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天锯蛀,我揣著相機(jī)與錄音,去河邊找鬼次慢。 笑死谬墙,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的经备。 我是一名探鬼主播拭抬,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼侵蒙!你這毒婦竟也來了造虎?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤纷闺,失蹤者是張志新(化名)和其女友劉穎算凿,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體犁功,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡氓轰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了浸卦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片署鸡。...
    茶點(diǎn)故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖限嫌,靈堂內(nèi)的尸體忽然破棺而出靴庆,到底是詐尸還是另有隱情,我是刑警寧澤怒医,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布炉抒,位于F島的核電站,受9級特大地震影響稚叹,放射性物質(zhì)發(fā)生泄漏焰薄。R本人自食惡果不足惜拿诸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望塞茅。 院中可真熱鬧亩码,春花似錦、人聲如沸凡桥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽缅刽。三九已至,卻和暖如春蠢络,著一層夾襖步出監(jiān)牢的瞬間衰猛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工刹孔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留啡省,地道東北人。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓髓霞,卻偏偏與公主長得像卦睹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子方库,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評論 2 348

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