欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中使用Lambda表達式和函數(shù)編程示例

 更新時間:2021年10月08日 14:44:12   作者:sofia  
這篇文章介紹了Java中使用Lambda表達式和函數(shù)編程示例,該文章會演示多個示列,分別是變量聲明上下文中的lambda、return語句上下文中的lambda、賦值上下文中的lambda、lambda在數(shù)組初始值設(shè)定項上下文中的用法等等,需要的朋友可以參考一下

1、簡單介紹

第一個示例演示變量聲明上下文中的lambda。它將lambda()->{System.out.println(“running”);}分配給可運行接口類型的變量r。

第二個示例類似,但演示了賦值上下文中的lambda(到先前聲明的變量r)。

第三個示例演示了return語句上下文中的lambda。它使用指定的文件擴展名參數(shù)調(diào)用getFilter()方法以返回java.io.FileFilter對象。該對象被傳遞給java.io.File的listFiles()方法,該方法為每個文件調(diào)用過濾器,忽略與擴展名不匹配的文件。getFilter()方法返回通過lambda表示的FileFilter對象。編譯器注意到lambda滿足此函數(shù)接口的boolean accept(文件路徑名)方法(兩者都有一個參數(shù),lambda主體返回一個布爾值),并將lambda綁定到FileFilter。

第四個示例演示了lambda在數(shù)組初始值設(shè)定項上下文中的用法?;趌ambdas創(chuàng)建了兩個java.nio.file.PathMatcher對象。每個PathMatcher對象根據(jù)其lambda主體指定的條件匹配文件。以下是相關(guān)代碼:

final PathMatcher matchers[] =
{
  (path) -> path.toString().endsWith("txt"),
  (path) -> path.toString().endsWith("java")
};


PathMatcher函數(shù)接口提供一個boolean matches(Path path)方法,該方法與lambda的參數(shù)列表及其主體的布爾返回類型一致。隨后調(diào)用此方法以確定在訪問當前目錄和子目錄期間遇到的每個文件的匹配項(基于文件擴展名)。

第五個示例演示線程構(gòu)造函數(shù)上下文中的lambda。

第六個示例演示了lambda上下文中的lambda,這表明lambda可以嵌套。

第七個示例演示了三元條件表達式(?:)上下文中的lambda:根據(jù)升序或降序排序從兩個lambda中選擇一個。

第八個(也是最后一個)示例演示了強制轉(zhuǎn)換表達式上下文中的lambda。()->System.getProperty(“user.name”)lambda被強制轉(zhuǎn)換為PrivilegedAction<String>函數(shù)接口類型。此強制轉(zhuǎn)換解決了java.security.AccessController類中的歧義,該類聲明了以下方法:

static <T> T doPrivileged(PrivilegedAction<T> action)
static <T> T doPrivileged(PrivilegedExceptionAction<T> action)


問題是PrivilegedActionPrivilegedExceptionAction的每個接口都聲明了相同的T run()方法。由于編譯器無法確定哪個接口是目標類型,因此在沒有強制轉(zhuǎn)換的情況下會報告錯誤。

編譯清單4并運行應(yīng)用程序。您應(yīng)該觀察以下輸出,該輸出假定LambdaDemo.java是當前目錄中唯一的.java文件,并且該目錄不包含.txt文件:

running
running
Found matched file: '.\LambdaDemo.java'.
running
called
Washington
Sydney
Rome
Ottawa
Moscow
London
Jerusalem
Berlin
jeffrey

2、Lambdas和Scopes

術(shù)語范圍是指程序中名稱與特定實體(例如變量)綁定的部分。在程序的另一部分中,名稱可能綁定到另一個實體。lambda主體不會引入新的作用域。相反,它的作用域是封閉作用域。

3、Lambdas與局部變量

lambda主體可以定義局部變量。因為這些變量被認為是封閉范圍的一部分,所以編譯器在檢測到lambda主體正在重新定義局部變量時將報告錯誤。清單5演示了這個問題。

清單5。LambdaDemo.java(版本5)

public class LambdaDemo
{
   public static void main(String[] args)
   {
      int limit = 10;
      Runnable r = () -> {
                           int limit = 5;
                           for (int i = 0; i < limit; i++)
                              System.out.println(i);
                         };
   }
}

因為limit已經(jīng)存在于封閉范圍(main()方法)中,lambda主體對limit的重新定義(int limit=5;)會導致編譯器報告以下錯誤消息:錯誤:變量limit已經(jīng)在方法main(字符串[])中定義。

4、Lambda體與局部變量

無論是源于lambda主體還是在封閉范圍內(nèi),局部變量在使用之前都必須初始化。否則,編譯器將報告錯誤。

在lambda主體外部定義并從主體引用的局部變量或參數(shù)必須標記為final或視為有效final(初始化后無法將該變量指定給)。試圖修改一個有效的最終變量會導致編譯器報告一個錯誤,如清單6所示。

清單6。LambdaDemo.java(版本6)

public class LambdaDemo
{
   public static void main(String[] args)
   {
      int limit = 10;
      Runnable r = () -> {
                           limit = 5;
                           for (int i = 0; i < limit; i++)
                              System.out.println(i);
                         };
   }
}

限制實際上是最終的。lambda主體試圖修改此變量會導致編譯器報告錯誤。這樣做是因為final/final變量需要掛起,直到lambda執(zhí)行為止,這可能要在定義變量的代碼返回后很久才會發(fā)生。非最終/非有效最終變量不再存在。

5、Lambdas和'This'和'Super'關(guān)鍵字

lambda主體中使用的任何thissuper引用都被視為等同于其在封閉范圍中的用法(因為lambda不引入新范圍)。然而,匿名類的情況并非如此,如清單7所示。

清單7。LambdaDemo.java(版本7)

public class LambdaDemo
{
   public static void main(String[] args)
   {
      new LambdaDemo().doWork();
   }
   public void doWork()
   {
      System.out.printf("this = %s%n", this);
      Runnable r = new Runnable()
                       {
                          @Override
                          public void run()
                          {
                             System.out.printf("this = %s%n", this);
                          }
                       };
      new Thread(r).start();
      new Thread(() -> System.out.printf("this = %s%n", this)).start();
   }
}

清單7的main()方法實例化LambdaDemo并調(diào)用對象的doWork()方法來輸出對象的this引用,實例化一個實現(xiàn)Runnable的匿名類,創(chuàng)建一個線程對象,在其線程啟動時執(zhí)行此Runnable,并創(chuàng)建另一個線程對象,其線程在啟動時執(zhí)行lambda。

編譯清單7并運行應(yīng)用程序。您應(yīng)該觀察與以下輸出類似的情況:

this = LambdaDemo@776ec8df
this = LambdaDemo$1@48766bb
this = LambdaDemo@776ec8df


第一行顯示LambdaDemo的this引用,第二行顯示新可運行范圍中不同的this引用,第三行顯示lambda上下文中的this引用。第三行和第一行匹配,因為lambda的作用域嵌套在doWork()方法中;這在整個方法中具有相同的含義。

6、Lambdas和Exceptions

lambda主體不允許拋出比函數(shù)接口方法的throws子句中指定的更多的異常。如果lambda主體拋出異常,則函數(shù)接口方法的throws子句必須聲明相同的異常類型或其超類型??紤]清單8。

清單8。LambdaDemo.java(版本8)

import java.awt.AWTException;
import java.io.IOException;
@FunctionalInterface
interface Work
{
   void doSomething() throws IOException;
}
public class LambdaDemo
{
   public static void main(String[] args) throws AWTException, IOException
   {
      Work work = () -> { throw new IOException(); };
      work.doSomething();
      work = () -> { throw new AWTException(""); };
   }
}

清單8聲明了一個工作函數(shù)接口,其doSomething()方法聲明為拋出java.io.IOException。main()方法將拋出IOExceptionlambda分配給work,這是正常的,因為IOException列在doSomething()的throws子句中。

main()接下來分配一個lambda,該lambda拋出java.awt.AWTException來工作。但是,編譯器不允許此賦值,因為AWTException不是doSomething()的throws子句的一部分(當然也不是IOException的子類型)。

7、預(yù)定義的功能接口

您可能會發(fā)現(xiàn)自己反復(fù)創(chuàng)建類似的功能接口。例如,您可以使用布爾IsConnection(連接c)方法創(chuàng)建CheckConnection函數(shù)接口,使用布爾isPositiveBalance(帳戶帳戶)方法創(chuàng)建CheckAccount函數(shù)接口。這是浪費。

前面的示例公開了謂詞(布爾值函數(shù))的抽象概念。Oracle提供了常用功能接口的java.util.function包,以預(yù)測這些模式。例如,這個包的Predicate<T>功能接口可以用來代替CheckConnectionCheckAccount。

Predicate<T>提供一個boolean test(T t)方法,該方法根據(jù)其argument (t)計算該謂詞,當T與predicate匹配時返回true,否則返回false。請注意,test()提供了與isConnected()isPositiveBalance()相同的參數(shù)列表。另外,請注意,它們都具有相同的返回類型(布爾值)。

清單9中的應(yīng)用程序源代碼演示了謂詞<T>。

清單9。LambdaDemo.java(版本9)

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
class Account
{
   private int id, balance;
   Account(int id, int balance)
   {
      this.balance = balance;
      this.id = id;
   }
   int getBalance()
   {
      return balance;
   }
   int getID()
   {
      return id;
   }
   void print()
   {
      System.out.printf("Account: [%d], Balance: [%d]%n", id, balance);
   }
}
public class LambdaDemo
{
   static List<Account> accounts;
   public static void main(String[] args)
   {
      accounts = new ArrayList<>();
      accounts.add(new Account(1000, 200));
      accounts.add(new Account(2000, -500));
      accounts.add(new Account(3000, 0));
      accounts.add(new Account(4000, -80));
      accounts.add(new Account(5000, 1000));
      // Print all accounts
      printAccounts(account -> true);
      System.out.println();
      // Print all accounts with negative balances.
      printAccounts(account -> account.getBalance() < 0);
      System.out.println();
      // Print all accounts whose id is greater than 2000 and less than 5000.
      printAccounts(account -> account.getID() > 2000 &&
                               account.getID() < 5000);
   }
   static void printAccounts(Predicate<Account> tester)
   {
      for (Account account: accounts)
         if (tester.test(account))
            account.print();
   }
}

清單9創(chuàng)建了一個基于數(shù)組的帳戶列表,其中有正余額、零余額和負余額。然后,它通過使用lambdas調(diào)用printAccounts()來演示謂詞<T>,以便打印出所有帳戶,僅打印出那些余額為負數(shù)的帳戶,以及僅打印出ID大于2000且小于5000的帳戶。

考慮lambda表達式帳戶->真。編譯器驗證lambda是否匹配謂詞<T>的布爾測試(T)方法,它會這樣做——lambda提供單個參數(shù)(account),其主體始終返回布爾值(true)。對于這個lambda,test()被實現(xiàn)為執(zhí)行return true;。

編譯清單9并運行應(yīng)用程序。我們能觀察以下輸出:

Account: [1000], Balance: [200]
Account: [2000], Balance: [-500]
Account: [3000], Balance: [0]
Account: [4000], Balance: [-80]
Account: [5000], Balance: [1000]
Account: [2000], Balance: [-500]
Account: [4000], Balance: [-80]
Account: [3000], Balance: [0]
Account: [4000], Balance: [-80]


Predicate<T>只是java.util.function的各種預(yù)定義函數(shù)接口之一。另一個示例是Consumer<T>,它表示接受單個參數(shù)但不返回結(jié)果的操作。與Predicate<T>不同,Consumer<T>預(yù)期通過副作用進行操作。換句話說,它以某種方式修改了它的論點。

使用者的void accept(T)方法對其argument(T)執(zhí)行操作。當出現(xiàn)在此函數(shù)接口的上下文中時,lambda必須符合accept()方法的單獨參數(shù)和返回類型。

到此這篇關(guān)于Java中使用Lambda表達式和函數(shù)編程示例的文章就介紹到這了,更多相關(guān)Java中使用Lambda表達式和函數(shù)編程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用java實現(xiàn)http多線程斷點下載文件(一)

    使用java實現(xiàn)http多線程斷點下載文件(一)

    Java 多線程斷點下載文件基本原理:利用URLConnection獲取要下載文件的長度、頭部等相關(guān)信息,并設(shè)置響應(yīng)的頭部信息,本文將詳細介紹,需要了解更多的朋友可以參考下
    2012-12-12
  • kafka生產(chǎn)實踐(詳解)

    kafka生產(chǎn)實踐(詳解)

    下面小編就為大家?guī)硪黄猭afka生產(chǎn)實踐(詳解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • Java多線程之原子類解析

    Java多線程之原子類解析

    這篇文章主要介紹了Java多線程之原子類解析,Java原子類是一種多線程編程中常用的工具,用于實現(xiàn)線程安全的操作,它們提供了一種原子性操作的機制,確保多個線程同時訪問共享變量時的數(shù)據(jù)一致性,需要的朋友可以參考下
    2023-10-10
  • 淺析JDK12的五大重要新特性(推薦)

    淺析JDK12的五大重要新特性(推薦)

    這篇文章主要介紹了JDK12的五大重要新特性,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-05-05
  • JavaWeb Session 會話管理實例詳解

    JavaWeb Session 會話管理實例詳解

    這篇文章主要介紹了JavaWeb Session 會話管理的相關(guān)資料,非常不錯,具有參考借鑒價值,感興趣的朋友一起看看吧
    2016-09-09
  • Spring Security 在 Spring Boot 中的使用詳解【集中式】

    Spring Security 在 Spring Boot 中的使用詳解【集中式】

    這篇文章主要介紹了Spring Security 在 Spring Boot 中的使用【集中式】,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-10-10
  • java實現(xiàn)文件導入導出

    java實現(xiàn)文件導入導出

    這篇文章主要介紹了java實現(xiàn)文件導入導出的方法和具體示例代碼,非常的簡單實用,有需要的小伙伴可以參考下
    2016-04-04
  • 最新評論