溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Java8新特性Lambda表達(dá)式怎么應(yīng)用

發(fā)布時(shí)間:2023-04-18 11:13:04 來(lái)源:億速云 閱讀:105 作者:iii 欄目:開(kāi)發(fā)技術(shù)

這篇文章主要介紹“Java8新特性Lambda表達(dá)式怎么應(yīng)用”,在日常操作中,相信很多人在Java8新特性Lambda表達(dá)式怎么應(yīng)用問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”Java8新特性Lambda表達(dá)式怎么應(yīng)用”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

    一、簡(jiǎn)介

    Java 8 (又稱為 jdk 1.8) 是 Java 語(yǔ)言開(kāi)發(fā)的一個(gè)主要版本。 Oracle 公司于 2014 年 3 月 18 日發(fā)布 Java 8 ,它支持函數(shù)式編程,新的 JavaScript 引擎,新的日期 API,新的Stream API 等。

     特征

    • 可選類(lèi)型聲明:不需要聲明參數(shù)類(lèi)型,編譯器可以統(tǒng)一識(shí)別參數(shù)值。

    • 可選的參數(shù)圓括號(hào):一個(gè)參數(shù)無(wú)需定義圓括號(hào),但多個(gè)參數(shù)需要定義圓括號(hào)。

    • 可選的大括號(hào):如果主體包含了一個(gè)語(yǔ)句,就不需要使用大括號(hào)。

    • 可選的返回關(guān)鍵字:如果主體只有一個(gè)表達(dá)式返回值則編譯器會(huì)自動(dòng)返回值,大括號(hào)需要指定表達(dá)式返回了一個(gè)數(shù)值。

     注意:Lambda表達(dá)式適用于只有一個(gè)抽象方法的接口?。?/strong>

    引入

    自定義接口

    interface Fu{
        void add();
    }

    使用匿名內(nèi)部類(lèi)實(shí)現(xiàn)接口

    Fu fu = new Fu() {
                @Override
                public void add() {
                    System.out.println("我是add方法");
                }
            };
            fu.add();

    使用Lambda表達(dá)式實(shí)現(xiàn)接口

            Fu fu1 = ()->{
                System.out.println("我是add1方法");
            };
            fu1.add();

    Lambda表達(dá)式的總結(jié)

    • Lambda表達(dá)式基于數(shù)學(xué)中的 入 演化得名的,對(duì)應(yīng)Java中的lambda抽象,是一個(gè)匿名函數(shù),就是沒(méi)有函數(shù)名的函數(shù)。

    • 好處

      • 使代碼更加簡(jiǎn)潔緊湊,且可與Stream API等相結(jié)合,Lambda表達(dá)式經(jīng)常代替匿名內(nèi)部類(lèi)使用

    • 語(yǔ)法

      • (參數(shù))->表達(dá)式或者(參數(shù))->{語(yǔ)句體;}

      • 參數(shù):要重寫(xiě)方法的參數(shù)列表

      • ->:Lambda表達(dá)式的運(yùn)算符

      • 表達(dá)式或語(yǔ)句體:要實(shí)現(xiàn)的方法的方法體

    • 本質(zhì)

      • 是一種匿名函數(shù)(不是匿名內(nèi)部類(lèi)),簡(jiǎn)單說(shuō),它沒(méi)有聲明的方法、沒(méi)有訪問(wèn)修飾符、返回值聲明和名字,它是屬于函數(shù)式編程的概念

    三、Lambda表達(dá)式的使用

    無(wú)參、無(wú)返回值

    接口

    interface F{
        void add();
    }

    測(cè)試

            //無(wú)參無(wú)返回值
            F f = ()->{
                System.out.println("我是add方法");
            };
            f.add();

    有參無(wú)返回值

    接口

    interface F{
        void add(int a);
    }

    測(cè)試

            F f = (int a)->{
                System.out.println("a="+a);
            };
            f.add(12);

    無(wú)參數(shù)有返回值

    接口

    interface F{
        int add();
    }

    測(cè)試

            F f = ()->{
                return 12;
            };
            int i = f.add();
            System.out.println(i);

    有參數(shù)有返回值

    接口

    interface F{
        int add(int a);
    }

    測(cè)試

            F f = (int a)->{
                return 12+a;
            };
            int i = f.add( 12 );
            System.out.println(i);

    四、Lambda表達(dá)式的注意事項(xiàng)

    • Lambda表達(dá)式中 () 的參數(shù)類(lèi)型可以省略 (int a,int b)==>(a,b)

    • 接口中如果只有一個(gè)參數(shù),Lambda表達(dá)式中 () 可以省略  (int a)==> (a)==>a

    • 如果方法體中只有一條執(zhí)行語(yǔ)句時(shí) 外層的 {} 可以省略

    • 如果方法體中只有一條返回語(yǔ)句,{}和return 都可以省略

     五、函數(shù)式接口

    函數(shù)式接口(Functional Interface)就是一個(gè)有且僅有一個(gè)抽象方法,可以有其他普通方法,用@FunctionalInterface檢驗(yàn)是否是函數(shù)式接口。

    @FunctionalInterface
    interface F1{
        void t1();
        
        default void t2(){//不計(jì)
            
        }
        static void t3(){//不計(jì)
            
        }
        public boolean equals(Object object);//不計(jì)
    }

    作用:在Java中主要用在Lambda表達(dá)式和方法引用。

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

    • Consumer<T>:消費(fèi)型接口(void accept(T t))。有參數(shù),無(wú)返回值

    • Supplier<T>:供給型接口(T get())。有參數(shù),無(wú)返回值

    • Function<T,R>:函數(shù)型接口(R apply(T t))。一個(gè)輸入?yún)?shù),一個(gè)輸出參數(shù),兩種類(lèi)型可以一致,也可以不一致

    • Predicate<T>:斷言型接口(boolean test(T t))。輸入一個(gè)參數(shù),輸出一個(gè)boolean類(lèi)型的返回值

    函數(shù)式接口使用場(chǎng)景

    消費(fèi)型接口

    //函數(shù)式接口的使用場(chǎng)景
    public class Test03 {
        public static void main(String[] args) {
            List<Integer> list = new ArrayList<>();
            Collections.addAll(list,1,2,3,6,5,4,8,9);
            //匿名內(nèi)部類(lèi)
            Consumer<Integer> con = new Consumer<Integer>() {
                @Override
                public void accept(Integer integer) {
                    //參數(shù)代表集合中的每一個(gè)數(shù)據(jù)
                    System.out.print(integer+" ");
                }
            };
            list.forEach( con );
            System.out.println();
            System.out.println("==================");
            //Lambda表達(dá)式1
            Consumer cons = (y)->{
                System.out.print(y+" ");
            };
            list.forEach( cons );
            System.out.println();
            System.out.println("==================");
            //Lambda表達(dá)式2
            list.forEach( y-> System.out.print(y+" ") );
        }
    }

    斷言型接口

    public class Test04 {
        public static void main(String[] args) {
            List<Integer> list = new ArrayList<>();
            Collections.addAll(list,1,2,3,6,5,4,8,9);
            //匿名內(nèi)部類(lèi)
            Predicate<Integer> predicate = new Predicate<Integer>() {
                @Override
                public boolean test(Integer integer) {
                    //參數(shù)o代表集合中的每一個(gè)數(shù)
                    if (integer<=6){
                        return true;//刪除該數(shù)據(jù)
                    }
                    return false;//不刪除該數(shù)據(jù)
                }
            };
            list.removeIf(predicate);
            list.forEach( x-> System.out.println(x) );
            System.out.println("=================");
     
            //Lambda表達(dá)式
            list.removeIf( y->{
                if (y<=6){
                    return true;
                }
                return false;
            } );
            list.removeIf(predicate);
            list.forEach( x-> System.out.println(x) );
            System.out.println("=================");
        }
    }

    六、方法調(diào)用

    方法引用通過(guò)方法的名字來(lái)指向一個(gè)方法。方法引用可以使語(yǔ)言的構(gòu)造更緊湊簡(jiǎn)潔,減少冗余代碼。方法引用使用一對(duì)冒號(hào) :: 。

    //方法引用
    public class Test05 {
        public static void main(String[] args) {
            List<Integer> list = new ArrayList<>();
            Collections.addAll(list,4,8,9);
     
            //使用Lambda表達(dá)式
            list.forEach( x-> System.out.println(x) );
            System.out.println("==================");
            //方法引用
            //使用場(chǎng)景,參數(shù)傳遞過(guò)來(lái)不做任何處理,直接輸出的就可以使用方法引用
            list.forEach(System.out::println);
        }
    }

    構(gòu)造器引用:它的語(yǔ)法是Class::new,或者更一般的Class< T >::new

    final Car car = Car.create( Car::new ); final List< Car > cars = Arrays.asList( car );

    靜態(tài)方法引用:它的語(yǔ)法是Class::static_method

    cars.forEach( Car::collide );

    特定類(lèi)的任意對(duì)象的方法引用:它的語(yǔ)法是Class::method

    cars.forEach( Car::repair );

    特定對(duì)象的方法引用:它的語(yǔ)法是instance::method

    final Car police = Car.create( Car::new ); cars.forEach( police::follow );

    七、Stream流式編程

    什么是 Stream?

    Stream(流)是一個(gè)來(lái)自數(shù)據(jù)源的元素隊(duì)列并支持聚合操作

    • 元素是特定類(lèi)型的對(duì)象,形成一個(gè)隊(duì)列。 Java中的Stream并不會(huì)存儲(chǔ)元素,而是按需計(jì)算。

    • 數(shù)據(jù)源 流的來(lái)源。 可以是集合,數(shù)組,I/O channel, 產(chǎn)生器generator 等。

    • 聚合操作 類(lèi)似SQL語(yǔ)句一樣的操作, 比如filter, map, reduce, find, match, sorted等。

    和以前的Collection操作不同, Stream操作還有兩個(gè)基礎(chǔ)的特征:

    • Pipelining: 中間操作都會(huì)返回流對(duì)象本身。 這樣多個(gè)操作可以串聯(lián)成一個(gè)管道, 如同流式風(fēng)格(fluent style)。 這樣做可以對(duì)操作進(jìn)行優(yōu)化, 比如延遲執(zhí)行(laziness)和短路( short-circuiting)。

    • 內(nèi)部迭代: 以前對(duì)集合遍歷都是通過(guò)Iterator或者For-Each的方式, 顯式的在集合外部進(jìn)行迭代, 這叫做外部迭代。 Stream提供了內(nèi)部迭代的方式, 通過(guò)訪問(wèn)者模式(Visitor)實(shí)現(xiàn)。

     使用 Stream流的步驟

    • 創(chuàng)建Stream:從一個(gè)數(shù)據(jù)源(集合、數(shù)組)中獲取

    • 中間操作:一個(gè)操作的中間鏈,對(duì)數(shù)據(jù)源的數(shù)據(jù)進(jìn)行處理

    • 終止操作:一個(gè)終止操作,執(zhí)行中間操作鏈,并產(chǎn)生結(jié)果

     排序去重

    //Stream 流式編程
    public class StreamTest01 {
        public static void main(String[] args) {
            //需求:有一堆數(shù)據(jù),且有重復(fù)值,要求有序去除重復(fù)值
            List<Integer> list = new ArrayList<>();
            Collections.addAll(list,56,89,75,64,24,25,24,89,56,75);
     
            //流式編程處理
            //獲取stream
            Stream<Integer> stream = list.stream();
            //中間操作
            stream = stream.distinct()//去重操作
                            .sorted();//排序
            //終止操作
            stream.forEach( x->{//輸出集合中元素
                System.out.println(x);
            } );
        }
    }

    中間操作

            stream = stream.distinct()//去重操作
                            .sorted();//排序
            .limit( 4 );//取前四個(gè)元素
            .skip( 2 );//跳過(guò)前幾個(gè)元素
            .map( x->x+4 );//每一個(gè)元素加上特定的值
            .filter( x->{//過(guò)濾操作,true正常返回,false不返回
                if (x>=25){
                    return true;
                }
                return false;
            } );

    八、串行流和并行流

    串行流

            Stream<Integer> stream = list.stream();//串行流

    并行流

            Stream<Integer> stream1 = list.parallelStream();//并行流

    九、Optional 類(lèi)

    • Optional 類(lèi)是一個(gè)可以為null的容器對(duì)象。如果值存在則isPresent()方法會(huì)返回true,調(diào)用get()方法會(huì)返回該對(duì)象。

    • Optional 是個(gè)容器:它可以保存類(lèi)型T的值,或者僅僅保存null。Optional提供很多有用的方法,這樣我們就不用顯式進(jìn)行空值檢測(cè)。

    • Optional 類(lèi)的引入很好的解決空指針異常。

      Optional 類(lèi)的方法

    • static <T> Optional<T> empty()        返回空的 Optional 實(shí)例。

    • boolean equals(Object obj)        判斷其他對(duì)象是否等于 Optional。

    • Optional<T> filter(Predicate<? super <T> predicate)        如果值存在,并且這個(gè)值匹配給定的 predicate,返回一個(gè)Optional用以描述這個(gè)值,否則返回一個(gè)空的Optional。

    • <U> Optional<U> flatMap(Function<? super T,Optional<U>> mapper)        如果值存在,返回基于Optional包含的映射方法的值,否則返回一個(gè)空的Optional

    • T get()        如果在這個(gè)Optional中包含這個(gè)值,返回值,否則拋出異常:NoSuchElementException

    • int hashCode()        返回存在值的哈希碼,如果值不存在 返回 0。

    • void ifPresent(Consumer<? super T> consumer)        如果值存在則使用該值調(diào)用 consumer , 否則不做任何事情。

    • boolean isPresent()        如果值存在則方法會(huì)返回true,否則返回 false

    • <U>Optional<U> map(Function<? super T,? extends U> mapper)        如果有值,則對(duì)其執(zhí)行調(diào)用映射函數(shù)得到返回值。如果返回值不為 null,則創(chuàng)建包含映射返回值的Optional作為map方法返回值,否則返回空Optional。

    • static <T> Optional<T> of(T value)        返回一個(gè)指定非null值的Optional。

    • static <T> Optional<T> ofNullable(T value)       如果為非空,返回 Optional 描述的指定值,否則返回空的 Optional。

    • T orElse(T other)       如果存在該值,返回值, 否則返回 other。

    • T orElseGet(Supplier<? extends T> other)       如果存在該值,返回值, 否則觸發(fā) other,并返回 other 調(diào)用的結(jié)果。

    • <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier)       如果存在該值,返回包含的值,否則拋出由 Supplier 繼承的異常

    •   String toString()     返回一個(gè)Optional的非空字符串,用來(lái)調(diào)試

    到此,關(guān)于“Java8新特性Lambda表達(dá)式怎么應(yīng)用”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!

    向AI問(wèn)一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI