自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

深入了解Java 8 新特性:lambda表達(dá)式進(jìn)階

開發(fā) 前端
Java的函數(shù)式編程就是Lambda表達(dá)式,java的函數(shù)式接口的有一個(gè)明顯特征:有且僅有一個(gè)抽象方法的接口。

前言

Java 8中的Lambda表達(dá)式是一種匿名函數(shù),它允許你將函數(shù)作為方法參數(shù)進(jìn)行傳遞,或者把代碼更簡潔地定義在你的應(yīng)用程序里。另外Java的函數(shù)式編程就是Lambda表達(dá)式,java的函數(shù)式接口的有一個(gè)明顯特征:有且僅有一個(gè)抽象方法的接口。下面是一些常見的Java內(nèi)置的函數(shù)式接口梳理,掌握這些內(nèi)置的函數(shù)式接口是相當(dāng)有必要的,因?yàn)樽鳛橐环N更簡潔、更靈活和更易于維護(hù)的編程方式,這在很多的java相關(guān)的框架技術(shù)中有大量的應(yīng)用,相信有喜歡鉆研源碼小伙伴應(yīng)該深有體會(huì)。

Java內(nèi)置的函數(shù)式接口

Function

Function接口是Java 8中引入的一個(gè)函數(shù)式接口,它位于java.util.function包中。這個(gè)接口表示一個(gè)輸入?yún)?shù)能夠產(chǎn)生一個(gè)結(jié)果的函數(shù)。Function接口只有一個(gè)抽象方法,即apply(T t),它接受一個(gè)參數(shù)并返回一個(gè)結(jié)果。

@FunctionalInterface
public interface Function<T, R> {


    R apply(T t);


    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }


    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }


    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

下面是一個(gè)使用Function接口的簡單示例:

@Test
public void test5() {
    Function<String, Student> function = str -> new Student(str);
    Student student = function.apply("張三");
    log.info(student.getName());
}

在Java中,Function接口的默認(rèn)實(shí)現(xiàn)包括以下幾種:

  • Function. andThen(Function after):這個(gè)方法返回一個(gè)新函數(shù),它首先應(yīng)用原始函數(shù),然后應(yīng)用另一個(gè)函數(shù)。也就是說,這個(gè)新函數(shù)首先將輸入映射到某個(gè)結(jié)果,然后將結(jié)果映射到另一個(gè)結(jié)果。假設(shè)我們有一個(gè)Function<Integer,Integer>,它接受一個(gè)整數(shù)作為輸入,并返回一個(gè)整數(shù)作為輸出?,F(xiàn)在,我們想在這個(gè)函數(shù)的基礎(chǔ)上添加一個(gè)新的函數(shù),將得到的整數(shù)加倍。
@Test
public void test7() {
    Function<Integer, Integer> originalFunction = x -> x * 2;
    Function<Integer, Integer> newFunction = x -> x * 2;
    Function<Integer, Integer> composedFunction = originalFunction.andThen(newFunction);
    int input = 5;
    int result = composedFunction.apply(input);
    System.out.println(result);  // 輸出:20
}

在上面的示例中,我們定義了一個(gè)原始函數(shù)originalFunction,它接受一個(gè)整數(shù)作為輸入,并將其乘以2。然后,我們定義了一個(gè)新的函數(shù)newFunction,它也接受一個(gè)整數(shù)作為輸入,并將其乘以2。接下來,我們使用andThen方法將這兩個(gè)函數(shù)組合成一個(gè)新的函數(shù)composedFunction。最后,我們將輸入整數(shù)5傳遞給composedFunction,并打印結(jié)果。在這個(gè)例子中,首先將輸入整數(shù)5乘以2得到10,然后將10乘以2得到20,最終輸出結(jié)果為20。

  • Function. compose(Function before):這個(gè)方法返回一個(gè)新函數(shù),它首先應(yīng)用另一個(gè)函數(shù),然后將結(jié)果映射到原始函數(shù)的輸入。也就是說,這個(gè)新函數(shù)首先將輸入映射到另一個(gè)輸入,然后將這個(gè)輸入映射到結(jié)果。假設(shè)我們有兩個(gè)函數(shù),一個(gè)將字符串轉(zhuǎn)換為大寫,另一個(gè)將字符串長度截?cái)酁?個(gè)字符。這兩個(gè)函數(shù)可以組合成一個(gè)新函數(shù),首先將字符串轉(zhuǎn)換為大寫,然后將其長度截?cái)酁?個(gè)字符。
@Test
public void test6(){
    Function<String, String> toUpperCase = str -> str.toUpperCase();
    Function<String, String> truncate = str -> str.substring(0, 6);
    Function<String, String> composedFunction = toUpperCase.compose(truncate);
    String input = "hello world!";
    String result = composedFunction.apply(input);
    System.out.println(result);  // 輸出:"HEL"
}

在上面的示例中,我們首先定義了兩個(gè)函數(shù):toUpperCase和truncate。然后,我們使用compose方法將它們組合成一個(gè)新函數(shù)composedFunction。最后,我們調(diào)用composedFunction對(duì)輸入字符串進(jìn)行操作,并打印結(jié)果。

BiFunction

BiFunction接口是Java 8中引入的一個(gè)函數(shù)式接口,它位于java.util.function包中。BiFunction接口表示一個(gè)接受兩個(gè)輸入?yún)?shù)并返回一個(gè)結(jié)果的函數(shù)。它與Function接口類似,但多了一個(gè)輸入?yún)?shù)。

BiFunction接口的定義如下:

@FunctionalInterface
public interface BiFunction<T, U, R> {


    R apply(T t, U u);
  
    default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t, U u) -> after.apply(apply(t, u));
    }
}

其中,TU是輸入?yún)?shù)的類型,R是返回結(jié)果的類型。apply()方法是抽象的,需要具體的實(shí)現(xiàn)來提供具體的邏輯。

下面是一個(gè)使用BiFunction接口的示例:

@Test
public void test8() {
    BiFunction<Integer, Integer, Integer> add = (x, y) -> x + y;
    int result = add.apply(2, 3);
    System.out.println(result);  // 輸出:5
}

在上面的示例中,我們定義了一個(gè)add函數(shù),它接受兩個(gè)整數(shù)作為輸入,并將它們相加得到一個(gè)整數(shù)作為結(jié)果。我們使用apply()方法調(diào)用該函數(shù)并傳遞兩個(gè)參數(shù)2和3,然后打印結(jié)果5。

BiFunction接口包含一個(gè)默認(rèn)實(shí)現(xiàn),即andThen方法,用于將兩個(gè)函數(shù)組合在一起。它接受一個(gè)BiFunction作為參數(shù),并返回一個(gè)新的函數(shù),該函數(shù)將先應(yīng)用原始函數(shù),然后應(yīng)用給定的函數(shù)。

@Test
public void test9() {
    BiFunction<Integer, Integer, String> addAndToString = (x, y) -> Integer.toString(x + y);
    Function<String, String> toUpperCase = str -> str.toUpperCase();
    BiFunction<Integer, Integer, String> composedFunction = addAndToString.andThen(toUpperCase);
    int input1 = 2;
    int input2 = 3;
    String result = composedFunction.apply(input1, input2);
    System.out.println(result);  // 輸出:"5"  
}

在上面的示例中,我們定義了一個(gè)addAndToString函數(shù),它接受兩個(gè)整數(shù)作為輸入,并將它們的和轉(zhuǎn)換為字符串。然后,我們定義了一個(gè)toUpperCase函數(shù),它接受一個(gè)字符串作為輸入,并將其轉(zhuǎn)換為大寫。接下來,我們使用andThen方法將兩個(gè)函數(shù)組合成一個(gè)新的函數(shù)composedFunction。最后,我們調(diào)用composedFunction對(duì)輸入整數(shù)2和3進(jìn)行操作,并打印結(jié)果"5"。首先將輸入整數(shù)2和3相加得到5,然后將5轉(zhuǎn)換為字符串"5",最后將字符串"5"轉(zhuǎn)換為大寫"5",最終輸出結(jié)果為"5"。

Predicate

Predicate 是 Java 中的一個(gè)函數(shù)式接口,它位于 java.util.function 包中。這個(gè)接口用于表示一個(gè)參數(shù)的謂詞(即,條件判斷),接收一個(gè)參數(shù)并返回一個(gè)布爾值,通常用于判斷參數(shù)是否滿足指定的條件

@FunctionalInterface
public interface Predicate<T> {


    boolean test(T t);


    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }


    default Predicate<T> negate() {
        return (t) -> !test(t);
    }


    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }


    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }


    @SuppressWarnings("unchecked")
    static <T> Predicate<T> not(Predicate<? super T> target) {
        Objects.requireNonNull(target);
        return (Predicate<T>)target.negate();
    }
}

Predicate接口的主要方法是 test(),它接收一個(gè)參數(shù)并返回一個(gè)布爾值。下面是一個(gè)簡單的例子:

@Test
public void test3(){
    Student student = new Student("張三");
    Predicate<Student> predicate= obj -> "張三".equals(obj.getName());
    boolean flag = predicate.test(student);
    Assert.isTrue(flag,"test fail");
    boolean flag2 = predicate.test(new Student("李四"));
    Assert.isTrue(flag2,"test fail");
}

Predicate:常用的四個(gè)方法:

  • boolean test(T t):對(duì)給定的參數(shù)進(jìn)行判斷(判斷邏輯由Lambda表達(dá)式實(shí)現(xiàn)),返回一個(gè)布爾值。
  • default Predicate negate():返回一個(gè)邏輯的否定,對(duì)應(yīng)邏輯非。
  • default Predicate and(Predicate other):返回一個(gè)組合判斷,對(duì)應(yīng)短路與。
  • default Predicate or(Predicate other):返回一個(gè)組合判斷,對(duì)應(yīng)短路或。
@Test
public void test4(){
    Student student = new Student("張三");
    Predicate<Student> predicate= obj -> "張三".equals(obj.getName());
    Predicate<Student> predicate2= obj-> "李四".equals(obj.getName());
    Predicate<Student> or = predicate2.or(predicate);
    boolean flag = or.test(student);
    Assert.isTrue(flag,"test fail");
    student.setName("李四");
    boolean flag2 = or.test(student);
    Assert.isTrue(flag2,"test fail");
    Predicate<Student> predicate3=obj->18==obj.getAge();
    student.setAge(18);
    Predicate<Student> and = predicate3.and(predicate2);
    boolean flag3 = and.test(student);
    Assert.isTrue(flag3,"test fail");
    student.setName("鐵蛋");
    boolean test = and.test(student);
    Assert.isTrue(test,"學(xué)生姓名不等于張三或者李四");
}

Consumer

Consumer接口代表了一個(gè)接受輸入?yún)?shù)并返回void的函數(shù)。它的主要作用是消費(fèi)輸入數(shù)據(jù),也就是說,對(duì)輸入進(jìn)行某種操作,但不返回任何結(jié)果。

@FunctionalInterface
public interface Consumer<T> {


    void accept(T t);
    
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}
Consumer接口的主要方法是void accept(T t):對(duì)給定的參數(shù)執(zhí)行此操作。
@Test
public void test2() {
    Student student = new Student("zhangsan");
    Consumer<String> nameConsumer = str -> student.setName(str);
    nameConsumer.accept("lisi");//設(shè)置學(xué)生的姓名為拼音-小寫
    log.info(student.getName());
    Assert.isTrue("lisi".equals(student.getName()), "test fail!");  
}

Consumer接口的默認(rèn)實(shí)現(xiàn),andThen方法,用于將兩個(gè)Consumer合并在一起。它允許你將一個(gè)操作(即第二個(gè)Consumer)附加到另一個(gè)操作(即第一個(gè)Consumer)的后面,以便在原始操作完成之后執(zhí)行附加操作。

下面是一個(gè)簡單的示例,演示如何使用andThen方法:

@Test
public void test2() {
    Student student = new Student("zhangsan");
    Consumer<String> nameConsumer = str -> student.setName(str);
    Consumer<String> nameConsumer2 = name -> student.setName(name.toUpperCase());
    Consumer<String> nameConsumer3 = nameConsumer.andThen(nameConsumer2);//設(shè)置學(xué)生的姓名為拼音-大寫
    nameConsumer3.accept("lisi");
    log.info(student.getName());
    Assert.isTrue("LISI".equals(student.getName()), "test fail!");
}

Supplier

這個(gè)接口表示一個(gè)不接受任何參數(shù)但返回結(jié)果的函數(shù)

@FunctionalInterface public interface Supplier<T> {    T get(); }

特點(diǎn):

  • 該方法不需要參數(shù),它會(huì)按照某種實(shí)現(xiàn)邏輯(由Lambda表達(dá)式實(shí)現(xiàn))返回一個(gè)數(shù)據(jù)。
  • Supplier接口也稱為生產(chǎn)型接口,如果我們指定了接口的泛型是什么類型,那么接口中的get方法就會(huì)生產(chǎn)什么類型的數(shù)據(jù)供我們使用。

使用示例:

private String getStuName(Supplier<Student> supplier) {
    String name = supplier.get().getName();
    return name;
}


@Test
public void test() {
    String name = this.getStuName(() -> new Student("zhangsan"));
    log.info(name);
    Assert.isTrue(name.equals("zhangsan"), "test fail");
}


責(zé)任編輯:武曉燕 來源: 凡夫貶夫
相關(guān)推薦

2021-05-05 11:31:15

JDK新特性Lambda表達(dá)式Java8

2012-06-26 10:03:58

JavaJava 8lambda

2023-12-29 08:54:02

Optional個(gè)性化服務(wù)

2013-04-07 15:44:26

Java8Lambda

2024-02-04 08:35:03

APIJava 8數(shù)據(jù)庫

2024-02-02 11:18:37

Java 8API對(duì)象

2013-04-07 10:04:03

Java8Lambda

2023-12-13 10:12:40

Python函數(shù)lambda

2015-08-04 09:16:20

JavaLambda表達(dá)式

2009-09-11 09:48:27

Linq Lambda

2009-09-09 13:01:33

LINQ Lambda

2009-09-15 15:18:00

Linq Lambda

2022-12-05 09:31:51

接口lambda表達(dá)式

2012-07-18 09:45:32

Java 8ScalaLambda

2009-08-10 10:06:10

.NET Lambda

2024-10-10 14:43:54

LambdaSpring編程

2009-08-27 09:44:59

C# Lambda表達(dá)

2009-09-17 10:40:22

Linq Lambda

2009-09-15 17:30:00

Linq Lambda

2009-09-17 09:44:54

Linq Lambda
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)