最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中Lambda表達(dá)式并行與組合行為

 更新時間:2017年02月23日 10:16:45   作者:hwding  
這篇文章主要介紹了Java中Lambda表達(dá)式并行與組合行為,非常不錯,具有參考借鑒價值,需要的朋友可以參考下

從串行到并行

串行指一個步驟一個步驟地處理,也就是通常情況下,代碼一行一行地執(zhí)行。

如果將我們常用的迭代器式的循環(huán)展開的話,就是串行執(zhí)行了循環(huán)體內(nèi)所定義的操作:

sum += arr.get(0);
sum += arr.get(1);
sum += arr.get(2);
//...

在書的一開始,就提到Java需要支持集合的并行計算(而Lambda為這個需求提供了可能)。

這些功能將全部被實現(xiàn)于庫代碼中,對于我們使用者,實現(xiàn)并行的復(fù)雜性被大大降低(最低程度上只需要調(diào)用相關(guān)方法)。

另外,關(guān)于并發(fā)與并行這兩個概念,其實是不同的,如果不明白的話請自行了解,在此只引用一句非常流行的話:

一個是關(guān)于代碼結(jié)構(gòu),一個是關(guān)于代碼執(zhí)行。

如果我們想將一個計算任務(wù)均勻地分配給CPU的四個內(nèi)核,我們會給每個核分配一個用于計算的線程,每個線程上進(jìn)行整個任務(wù)的子任務(wù)。

書上有一段非常形象的偽代碼:

if the task list contains more than N/4 elements {
 leftTask = task.getLeftHalf()
 rightTask = task.getRightHalf()
 doInparallel {
 leftResult = leftTask.solve()
 rightResult = rightTask.solve()
 }
 result = combine(leftResult, rightResult)
} else {
 result = task.solveSequentially()
}

代碼中,將每四個任務(wù)元素分為一組,用四個內(nèi)核對其進(jìn)行并行處理,然后每兩組進(jìn)行一次結(jié)果的合并,最終得到整個任務(wù)隊列的最終結(jié)果。

從整體處理流程上看,先將任務(wù)隊列遞歸地進(jìn)行分組,并行處理每一組,然后將結(jié)果遞歸地進(jìn)行合并(合并通過管道終止操作實現(xiàn))。

Java8之前,開發(fā)者們使用一種針對集合的fork/join框架來實現(xiàn)該模式。

然而現(xiàn)在,想對代碼進(jìn)行性能優(yōu)化,就是一件非常容易的事了。

還記得我們上一節(jié)中所得出的最終代碼:

long validContactCounter = contactList.stream()
 .map(s -> new Contact().setName(s))
 .filter(Contact::call)
 .count();

稍加改動:

long validContactCounter = contactList.parallelStream()
 .map(s -> new Contact().setName(s))
 .filter(Contact::call)
 .count();

注意stream()變?yōu)閜arallelStream()

同時下圖將展示如何根據(jù)四個核對上述任務(wù)進(jìn)行分解處理,最終合并結(jié)果并終止管道。

注意遞歸分解的目的是使子任務(wù)們足夠小來串行執(zhí)行。

組合行為

Java寫手應(yīng)該知道,Java中并不存在純粹的“函數(shù)”,只存在“方法”。也就是說,Java中的函數(shù)必須依賴于某一個類,或者作為類的某種行為存在。

而在其他語言中,存在純函數(shù),以CoffeeScript的語法,聲明一個函數(shù):

eat = (x) -> 
 alert("#{x} has been eatten!")

這種寫法與Lambda表達(dá)式的語法非常相近,也就是說,相比于匿名內(nèi)部類,Lambda表達(dá)式看上去更像是一種函數(shù)表達(dá)式。

對于函數(shù),一個核心操作便是組合。如果要求一元二次函數(shù)的其中一個解sqrt(sqr(b) - 4 * a * c),便是對多個子函數(shù)進(jìn)行了組合。

對于面向?qū)ο?,我們通過解耦的方式來分解它,同樣,我們也希望以此種方式分解一個函數(shù)行為。

首先,沿用上兩節(jié)中使用的例子,對Contact類稍作修改,將name屬性分拆為名和姓:

private String firstName;
private String lastName;

假設(shè)我們現(xiàn)在想要對聯(lián)系人們進(jìn)行排序,創(chuàng)建自定義排序的Java標(biāo)準(zhǔn)方式是創(chuàng)建一個Comparator:

public interface Comparator<T> {
 int compare(T o1, T o2);
 //...
}

我們想通過比較名的首字母來為聯(lián)系人排序:

Comparator<Contact> byFirstName = new Comparator<Contact>() {
 @Override
 public int compare(Contact o1, Contact o2) {
 return Character.compare(o1.getFirstName().charAt(0), o2.getFirstName().charAt(0));
 }
};

Lambda寫法:

Comparator<Contact> byFirstNameLambdaForm = (o1, o2) ->
 Character.compare(o1.getFirstName().charAt(0), o2.getFirstName().charAt(0));

寫完這段代碼后,IDEA立即提醒我代碼可以替換為Comparator.comparingInt(...),不過這是后話,暫且不表。

在上面的代碼中,我們發(fā)現(xiàn)了組合行為,即Comparator<Contact>的compare(...)方法里面還套用了o.getFirstName()與Character.compare(...)這兩個方法(為了簡潔,這里暫不考慮charAt(...)),在java.util.function中,我們找到了這種函數(shù)的原型:

public interface Function<T, R> {
 R apply(T t);
 //...
}

接收一個T類型的參數(shù),返回一個R類型的結(jié)果。

現(xiàn)在我們將“比較名的首字母”這個比較鍵的提取行為抽成一個函數(shù)對象的實例:

Function<Contact, Character> keyExtractor = o -> o.getFirstName().charAt(0);

再將“比較首字母”這個具體的比較行為抽出來:

Comparator<Character> keyComparator = (c1, c2) -> Character.compare(c1, c2);

有了keyExtractor和keyComparator,我們再來重新裝配一下Comparator:

Comparator<Contact> byFirstNameAdvanced = (o1, o2) ->
 keyComparator.compare(keyExtractor.apply(o1), keyExtractor.apply(o2));

到了這一步,我們犧牲了簡潔性,但獲得了相應(yīng)的靈活性,也就是說,如果我們改變比較鍵為姓而非名,只需改動keyExtractor為:

Function<Contact, Character> keyExtractor = o -> o.getLastName().charAt(0);

值得慶幸的是,庫的設(shè)計者考慮到了這一自然比較的需求的普遍性,因此為Comparator接口提供了靜態(tài)方法comparing(...),只需傳入比較鍵的提取規(guī)則,就能針對該鍵生成相應(yīng)的Comparator,是不是非常神奇:

Comparator<Contact> compareByFirstName = Comparator.comparing(keyExtractor);

即使我們想改變比較的規(guī)則,比如比較聯(lián)系人姓與名的長度,也只需做些許改動:

Comparator<Contact> compareByNameLength = Comparator.comparing(p -> (p.getFirstName() + p.getLastName()).length());

這是一個重大的改進(jìn),它將我們所關(guān)注的焦點真正集中在了比較的規(guī)則上面,而不是大量地構(gòu)建所必須的膠水代碼。

comparing(...)通過接收一個簡單的行為,進(jìn)而基于這個行為構(gòu)造出更加復(fù)雜的行為。

贊!

然而更贊的是,對于流和管道,我們所需要的改動甚至更少:

contacts.stream()
 .sorted(compareByNameLength)
 .forEach(c -> System.out.println(c.getFirstName() + " " + c.getLastName()));

小結(jié)

本章的代碼:

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.function.Function;
public class Bar {
 public static void main(String[] args) {
//    long validContactCounter = contactList.parallelStream()
//    .map(s -> new Contact().setFirstName(s))
//    .filter(Contact::call)
//    .count();
  List<Contact> contacts = new ArrayList<Contact>() {{
   add(new Contact().setFirstName("Foo").setLastName("Jack"));
   add(new Contact().setFirstName("Bar").setLastName("Ma"));
   add(new Contact().setFirstName("Olala").setLastName("Awesome"));
  }};
  Comparator<Contact> byFirstName = new Comparator<Contact>() {
   @Override
   public int compare(Contact o1, Contact o2) {
    return Character.compare(o1.getFirstName().charAt(0), o2.getFirstName().charAt(0));
   }
  };
  //--- Using Lambda form ---//
  Comparator<Contact> byFirstNameLambdaForm = (o1, o2) ->
    Character.compare(o1.getFirstName().charAt(0), o2.getFirstName().charAt(0));
  Function<Contact, Character> keyExtractor = o -> o.getFirstName().charAt(0);
  Comparator<Character> keyComparator = (c1, c2) ->
    Character.compare(c1, c2);
  Comparator<Contact> byFirstNameAdvanced = (o1, o2) ->
    keyComparator.compare(keyExtractor.apply(o1), keyExtractor.apply(o2));
  Comparator<Contact> compareByFirstName = Comparator.comparing(keyExtractor);
  Comparator<Contact> compareByNameLength = Comparator.comparing(p -> (p.getFirstName() + p.getLastName()).length());
  contacts.stream()
    .sorted(compareByNameLength)
    .forEach(c -> System.out.println(c.getFirstName() + " " + c.getLastName()));
 }
}

以及運行結(jié)果:

Bar Ma
Foo Jack
Olala Awesome

以上所述是小編給大家介紹的Java中Lambda表達(dá)式并行與組合行為,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!

相關(guān)文章

  • 解決SpringCloud下spring-boot-maven-plugin插件的打包問題

    解決SpringCloud下spring-boot-maven-plugin插件的打包問題

    這篇文章主要介紹了SpringCloud下spring-boot-maven-plugin插件的打包問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-03-03
  • SpringBoot中的static靜態(tài)資源訪問、參數(shù)配置、代碼自定義訪問規(guī)則詳解

    SpringBoot中的static靜態(tài)資源訪問、參數(shù)配置、代碼自定義訪問規(guī)則詳解

    這篇文章主要介紹了SpringBoot的static靜態(tài)資源訪問、參數(shù)配置、代碼自定義訪問規(guī)則,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-07-07
  • Java圖片壓縮三種高效壓縮方案詳細(xì)解析

    Java圖片壓縮三種高效壓縮方案詳細(xì)解析

    圖片壓縮通常涉及減少圖片的尺寸縮放、調(diào)整圖片的質(zhì)量(針對JPEG、PNG等)、使用特定的算法來減少圖片的數(shù)據(jù)量等,這篇文章主要介紹了Java圖片壓縮三種高效壓縮方案的相關(guān)資料,需要的朋友可以參考下
    2025-04-04
  • 詳解Java中日期工具類的操作

    詳解Java中日期工具類的操作

    這篇文章主要為大家詳細(xì)介紹了Java中日期工具類的常見操作,如:字符串和Date互轉(zhuǎn)、字符串和LocalDate互轉(zhuǎn)等,感興趣的小伙伴可以學(xué)習(xí)一下
    2022-11-11
  • SpringBoot Security密碼加鹽實例

    SpringBoot Security密碼加鹽實例

    這篇文章主要為打擊介紹了SpringBoot Security密碼加鹽實例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • 解決無法解析javax.servlet的方法

    解決無法解析javax.servlet的方法

    最近在創(chuàng)建一個servlet時,自動生成的代碼中出現(xiàn)servlet無法解析的提示,令我無法正常使用servlet里的方法,在對各個步驟進(jìn)行查看后,發(fā)現(xiàn)了問題所在,需要的朋友可以參考下
    2021-05-05
  • Java代碼實現(xiàn)微信頁面滾動防露底(核心代碼)

    Java代碼實現(xiàn)微信頁面滾動防露底(核心代碼)

    這篇文章主要介紹了Java代碼實現(xiàn)微信頁面滾動防露底的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-09-09
  • 面試JAVA時,問到spring該怎么回答

    面試JAVA時,問到spring該怎么回答

    這篇文章主要介紹了Spring面試資料,學(xué)Java的小伙伴都知道Spring是面試的必問環(huán)節(jié),看完了一天就可掌握數(shù)據(jù)結(jié)構(gòu)和算法的面試題,快來看看吧
    2021-08-08
  • Java實現(xiàn)自定義語言和表達(dá)式解析的解釋器模式

    Java實現(xiàn)自定義語言和表達(dá)式解析的解釋器模式

    Java解釋器設(shè)計模式通過解析自定義語言和表達(dá)式,實現(xiàn)對復(fù)雜邏輯的處理,提高程序可擴展性和靈活性。它將語法解析和執(zhí)行過程分離,通過抽象語法樹和解釋器實現(xiàn)對語言和表達(dá)式的解析和求值,避免了硬編碼和復(fù)雜的條件判斷,提高了程序的可讀性和可維護(hù)性
    2023-04-04
  • Ubuntu 16.04 安裝 java 8的方法

    Ubuntu 16.04 安裝 java 8的方法

    這篇文章主要介紹了Ubuntu 16.04 安裝 java 8的方法,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-05-05

最新評論

澄迈县| 嘉荫县| 厦门市| 诸城市| 万载县| 紫阳县| 建始县| 招远市| 昭平县| 武宣县| 西平县| 镇雄县| 唐山市| 集安市| 神池县| 淮安市| 巩义市| 苍山县| 陆丰市| 邓州市| 栖霞市| 台安县| 吴江市| 乌拉特前旗| 内江市| 永吉县| 西畴县| 商城县| 福州市| 吴江市| 革吉县| 金乡县| 广德县| 鄂托克旗| 霍州市| 西和县| 昆明市| 华阴市| 共和县| 永州市| 海安县|