国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - Java中Lambda表達式并行與組合行為

Java中Lambda表達式并行與組合行為

2020-08-18 11:24hwding Java教程

這篇文章主要介紹了Java中Lambda表達式并行與組合行為,非常不錯,具有參考借鑒價值,需要的朋友可以參考下

從串行到并行

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

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

?
1
2
3
4
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)核,我們會給每個核分配一個用于計算的線程,每個線程上進行整個任務(wù)的子任務(wù)。

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

?
1
2
3
4
5
6
7
8
9
10
11
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)核對其進行并行處理,然后每兩組進行一次結(jié)果的合并,最終得到整個任務(wù)隊列的最終結(jié)果。

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

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

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

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

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

稍加改動:

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

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

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

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

組合行為

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

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

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

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

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

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

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

?
1
2
private String firstName;
private String lastName;

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

?
1
2
3
4
public interface Comparator<T> {
 int compare(T o1, T o2);
 //...
}

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

?
1
2
3
4
5
6
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寫法:

?
1
2
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ù)的原型:

?
1
2
3
4
public interface Function<T, R> {
 R apply(T t);
 //...
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

贊!

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

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

小結(jié)

本章的代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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é)果:

?
1
2
3
Bar Ma
Foo Jack
Olala Awesome

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

原文鏈接:http://www.cnblogs.com/hwding/p/6398361.html

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 四房婷婷 | 国产一区二区免费 | 6080夜射猫 | 国产精品久久久久久婷婷天堂 | 91亚洲国产成人久久精品网站 | 亚洲黄色成人 | 激情五月婷婷丁香 | 日韩中文字幕一区二区三区 | 91免费精品 | 亚洲 欧美 日韩在线 | 欧美中文字幕一区二区三区亚洲 | 久久久久久久久久久久久大色天下 | 黄色av网站免费 | 欧美精品一区二区三区在线 | 国产高清视频一区二区 | 成人免费视频网 | 国产成人av在线 | 久久久精品亚洲 | 成人免费在线播放 | 中文字幕综合 | 日韩精品一区二区三区第95 | 国产二区视频 | 国产一区二区三区在线免费观看 | 国产麻豆一区二区三区 | 一区二区国产在线观看 | 一区二区三区视频免费在线观看 | 国产999精品久久久久久麻豆 | 亚洲色图在线观看 | 久久久国产精品 | 国产精品久久久久久亚洲调教 | 午夜视频网 | 久久综合激情 | 亚洲精品日日夜夜 | 九九综合九九 | 久久久久久久久久久九 | 青青草视频在线免费观看 | 国内精品久久久久久中文字幕 | 成人性做爰av片免费看 | 韩国一区二区视频 | 欧美一区在线看 | 香蕉久久av一区二区三区 |