激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務器之家 - 編程語言 - Java教程 - 淺談JAVA8給我帶了什么——流的概念和收集器

淺談JAVA8給我帶了什么——流的概念和收集器

2021-07-27 11:50落葉隨風 Java教程

這篇文章主要介紹了JAVA8流的概念和收集器,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

到現在為止,筆者不敢給流下定義,從概念來講他應該也是一種數據元素才是??墒窃谖覀兦懊娴拇a例子中我們可以看到他更多的好像在表示他是一組處理數據的行為組合。這讓筆者很難去理解他的定義。所以筆者不表態。各位同志自行理解吧。

在沒有流以前,處理集合里面的數據一般都會用到顯示的迭代器。用一下前面學生的例子吧。目標是獲得學分大于5的前倆位同學。

?
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package com.aomi;
 
import java.util.arraylist;
import java.util.iterator;
import java.util.list;
import static java.util.stream.collectors.tolist;
 
public class main {
 
 public static void main(string[] args) {
  // todo auto-generated method stub
 
  list<student> stus = getsources();
 
  iterator<student> ite = stus.iterator();
 
  list<string> names = new arraylist<>();
  int limit = 2;
  while (ite.hasnext() && limit > 0) {
 
   student stu = ite.next();
 
   if (stu.getscore() > 5) {
 
    names.add(stu.getname());
    limit--;
   }
  }
 
  for (string name : names) {
   system.out.println(name);
  }
 
 }
 
 public static list<student> getsources() {
  list<student> students = new arraylist<>();
 
  student stu1 = new student();
 
  stu1.setname("lucy");
  stu1.setsex(0);
  stu1.setphone("13700227892");
  stu1.setscore(9);
 
  student stu2 = new student();
  stu2.setname("lin");
  stu2.setsex(1);
  stu2.setphone("15700227122");
  stu2.setscore(9);
 
  student stu3 = new student();
  stu3.setname("lili");
  stu3.setsex(0);
  stu3.setphone("18500227892");
  stu3.setscore(8);
 
  student stu4 = new student();
 
  stu4.setname("dark");
  stu4.setsex(1);
  stu4.setphone("16700555892");
  stu4.setscore(6);
 
  students.add(stu1);
  students.add(stu2);
  students.add(stu3);
  students.add(stu4);
 
  return students;
 }
 
}

如果用流的話是這樣子的。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void main(string[] args) {
  // todo auto-generated method stub
 
  list<student> stus = getsources();
 
  list<string> names = stus.stream()
    .filter(st -> st.getscore() > 5)
    .limit(2)
    .map(st -> st.getname())
    .collect(tolist());
  for (string name : names) {
   system.out.println(name);
  }
 
 }

把這倆段代碼相比較主要是為了說明一個概念:以前做法都是在外部迭代,最為體現就是筆者在外面定義了一個集合names 。而流卻什么也沒有,現在我們應該能清楚感受到流是在內部迭代。也就是說流已經幫你做好了迭代。我們只要傳入相關的函數就可以得到想要的結果。至于內部迭代的好處,筆者沒有辦法親身的感受,唯一的感覺就是代碼變的簡單明了了。但是官方說stream庫為了我們在內部迭代里面做了很多優化和充公利用性能的操作。比如并行操作。所以筆者就聽官方了。

事實上,在用流的過程中,我們用到很多方法函數。比如上面的limit方法,filter方法等。這個定義為流操作。但是不管是什么操作,你必須要有一個數據源吧??偨Y如下:

  1. 數據源:用于生成流的數據,比如集合。
  2. 流操作:類似于limit方法,filter方法。

流還有一種特點——部分流操作是沒有執行的。一般都是在collect函數執行的時候,才開始執行個個函數。所以我們可以細分一下流操作:

  1. 數據源:用于生成流的數據,比如集合。
  2. 中間操作:類似于limit方法,filter方法。這些操作做變了一個操作鏈,有一點流水線的概念。
  3. 終端操作:執行上面的操作鏈。比如collect函數。

從上面的講解我們就可以感覺流好像是先收集相關的目標操作,什么意思呢?就是先把要做的事情計劃一下,最后一聲令下執行。而下這個命令是collect函數。這一點跟.net的linq是很像的。同時記得他只能執行一次。也就是說這個流執行一次之后,就不可能在用了。
筆者列一下以前的用到的函數

foreach:終端
collect:終端
count:終端
limit:中間
filter:中間
map:中間
sorted:中間

到目前為止我們用到的流都是通過集合來建一個流。筆者對此從來沒有講過?,F在筆者來講些構建流的方式。
在stream庫里面為我們提供了這樣子一個方法——stream.of

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.aomi;
 
import java.util.optional;
import java.util.stream.stream;
 
public class main {
 
    public static void main(string[] args) {
        // todo auto-generated method stub
 
        stream stream = stream.of("i", "am", "aomi");
 
        optional<string> firstword = stream.findfirst();
        
        if(firstword.ispresent())
        {
            system.out.println("第一個字:"+firstword.get());
        }
    }
 
}

運行結果:

淺談JAVA8給我帶了什么——流的概念和收集器

去看一下of方法的代碼。如下

?
1
2
3
public static<t> stream<t> of(t... values) {
  return arrays.stream(values);
 }

說明我們可能指定一個類型來建一個流。上面可以修改為

?
1
stream<string> stream = stream.of("i", "am", "aomi");

findfirst函數用于表示返回第一個值。那就是可能數據源是一個空呢?所以他有可以會返回null。所以就是用一個叫optional類的表示可以為空。這樣子我們就可以用optional類的方法進一步做安全性的操作。比如判斷有沒有值(ispresent())
筆者想要建一個int類型的數組流玩玩。為了方便筆者便試給一下上面的代碼。卻發現報錯了。

淺談JAVA8給我帶了什么——流的概念和收集器

如果我把int改為integer呢?沒有問題了。所以注意要用引用類型的。int類型對應為integer類型。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.aomi;
 
import java.util.optional;
import java.util.stream.stream;
 
public class main {
 
 public static void main(string[] args) {
  // todo auto-generated method stub
 
  stream<integer> stream = stream.of(1, 2, 9);
 
  optional<integer> firstword = stream.findfirst();
  
  if(firstword.ispresent())
  {
   system.out.println("第一個字:"+firstword.get());
  }
 
 }
 
}

運行結果:

淺談JAVA8給我帶了什么——流的概念和收集器

那想要用int類型呢?什么辦呢?改改

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.aomi;
 
import java.util.optionalint;
import java.util.stream.intstream;
 
public class main {
 
 public static void main(string[] args) {
  // todo auto-generated method stub
 
  intstream stream = intstream.of(1, 2, 9);
 
  optionalint firstword = stream.findfirst();
  
  if(firstword.ispresent())
  {
   system.out.println("第一個字:"+firstword.getasint());
  }
 
 }
 
}

運行結果:

淺談JAVA8給我帶了什么——流的概念和收集器

我們以上面的例子來一個猜測:是不是double類型,只要修改為doublestream就行呢?試試。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.aomi;
 
import java.util.optionaldouble;
import java.util.stream.doublestream;
 
public class main {
 
 public static void main(string[] args) {
  // todo auto-generated method stub
 
  doublestream stream = doublestream.of(1.3, 2.3, 9.5);
 
  optionaldouble firstword = stream.findfirst();
  
  if(firstword.ispresent())
  {
   system.out.println("第一個字:"+firstword.getasdouble());
  }
 
 }
 
}

運行結果:

淺談JAVA8給我帶了什么——流的概念和收集器

結果很明顯,我們的猜測是對的。所以見意如果你操作的流是一個int或是double的話,請進可能的用xxxstream 來建流。這樣子在流的過程中不用進行拆裝和封裝了。必竟這是要性能的。在看一下如果數據源是一個數組的情況我們如何生成流呢?

?
1
2
3
4
5
6
7
8
public static collector<charsequence, ?, string> joining(charsequence delimiter,
                charsequence prefix,
                charsequence suffix) {
  return new collectorimpl<>(
    () -> new stringjoiner(delimiter, prefix, suffix),
    stringjoiner::add, stringjoiner::merge,
    stringjoiner::tostring, ch_noid);
 }

在看一個叫tolist函數的代碼。

?
1
2
3
4
5
6
public static <t>
 collector<t, ?, list<t>> tolist() {
   return new collectorimpl<>((supplier<list<t>>) arraylist::new, list::add,
         (left, right) -> { left.addall(right); return left; },
         ch_id);
 }

我們發現他會共同的返回一個collector類型。從上面我們就可以知道他的任務就是用去處理最后數據。我們把他定為收集器。讓我們看一下收集器的接口代碼吧;

?
1
2
3
4
5
6
7
8
9
10
11
12
public interface collector<t, a, r> {
 
 supplier<a> supplier();
 
 biconsumer<a, t> accumulator();
 
 binaryoperator<a> combiner();
 
 function<a, r> finisher();
 
 set<characteristics> characteristics();
}

光看前面四個方法是不是有一點熟悉的感覺。想要說明這個五個方法的作用。就必須明白一個概念——并行歸約。前面筆者講過流是一個內部迭代,也說stream庫為我們做一個很多優化的事情。其中一個就是并行。他用到了java 7引入的功能——分支/合并框架。也就是說流會以遞歸的方式拆分成很多子流,然后子流可以并行執行。最后在倆倆的子流的結果合并成一個最終結果。而這倆倆合并的行為就叫歸約 。如圖下。引用于《java8實戰》

淺談JAVA8給我帶了什么——流的概念和收集器

淺談JAVA8給我帶了什么——流的概念和收集器

我們必須根據圖上的意思來走。子流的圖里面會調用到collector類的三個方法。

  1. supplier方法:用創建數據存儲的地方。
  2. accumulator方法:用于子流執行過程的迭代工作。即是遍歷每一項都會執行。所以可以這里做一些工作。
  3. finisher方法:返回最后的結果,你可以在這里進一步處理結果。

每一個子流結束這之后,就是倆倆合并。這個時候就要看流的機制圖了。

  1. combiner方法:會傳入每一個子流的結果過來,我們就可以在這里在做一些工作。
  2. finisher方法:返回最后的結果。同上面子流的一樣子。

好像沒有characteristics什么事情。不是這樣子的。這個方法是用來說明當前這個流具備哪些優化。這樣子執行流的時候,就可以很清楚的知道要以什么樣子的方式執行了。比如并行。
他是一個enum類。值如下

  1. unordered:這個表示執行過程中結果不受歸約和遍歷的影響
  2. concurrent:表示可以多個線和調用accumulator方法。并且可以執行并行。當然前無序數據的才并行。除非收集器標了unordered。
  3. identity_finish:表示這是一個恒等函數,就是做了結果也一樣子。不用做了可以跳過了。

由了上面的講說明,我們在來寫一個自己的收集器吧——去除相同的單詞
distinctwordcollector類:

?
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package com.aomi;
 
import java.util.arraylist;
import java.util.collections;
import java.util.enumset;
import java.util.list;
import java.util.set;
import java.util.function.biconsumer;
import java.util.function.binaryoperator;
import java.util.function.function;
import java.util.function.supplier;
import java.util.stream.collector;
 
public class distinctwordcollector implements collector<string, list<string>, list<string>> {
 
 @override
 public supplier<list<string>> supplier() {
  // todo auto-generated method stub
  return () -> new arraylist<string>();
 }
 
 /**
  * 子流的處理項的過程
  */
 @override
 public biconsumer<list<string>, string> accumulator() {
  // todo auto-generated method stub
  return (list<string> src, string val) -> {
 
   if (!src.contains(val)) {
    src.add(val);
   }
  };
 }
 
 /**
  * 倆倆并合的執行函數
  */
 @override
 public binaryoperator<list<string>> combiner() {
  // todo auto-generated method stub
  return (list<string> src1, list<string> src2) -> {
   for (string val : src2) {
    if (!src1.contains(val)) {
     src1.add(val);
    }
   }
   return src1;
  };
 }
 
 @override
 public function<list<string>, list<string>> finisher() {
  // todo auto-generated method stub
  return function.identity();
 }
 
 @override
 public set<characteristics> characteristics() {
  // todo auto-generated method stub
  return collections.unmodifiableset(enumset.of(characteristics.identity_finish, characteristics.concurrent));
 }
 
}

 main:

?
1
2
3
4
5
6
7
8
9
10
11
public static void main(string[] args) {
  // todo auto-generated method stub
 
  list<string> words = arrays.aslist("aomi","lili","lucy","aomi","nono");
 
  list<string> vals = words.stream().collect(new distinctwordcollector());
  
  for (string val : vals) {
   system.out.println(val);
  }
 }

運行結果

淺談JAVA8給我帶了什么——流的概念和收集器

結果確定就是我們想要的——去掉了重復的aomi

以上所述是小編給大家介紹的java8流的概念和收集器詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 免费一及片 | 国产一区二区精品免费 | 久草热久草视频 | 亚洲一区二区三区在线看 | 日本网站在线看 | 一级做a爱片久久毛片a高清 | 久热久操 | 欧美一级特级 | 国产高清成人久久 | 四季久久免费一区二区三区四区 | 97黄色网| 亚洲一二区视频 | 免费观看一级 | 亚洲尻逼视频 | 成年人在线视频免费 | 日本高清黄色片 | 久久草在线看 | 欧美日韩一区三区 | 日韩一级片 | 日韩精品网站在线观看 | 亚洲视频观看 | 久久国产中文 | 激情夜色 | 久久艹精品 | 国产一区二区在线免费播放 | 亚洲精品午夜在线 | 国产高清美女一级毛片 | 成人福利在线看 | 久草最新网址 | 黄色网页在线观看 | 色综合激情 | 久久露脸国语精品国产91 | 久久99精品久久久久久园产越南 | 黄色视品 | 国产美女做爰免费视 | 91av在线国产 | 亚州精品天堂中文字幕 | 99久久自偷自偷国产精品不卡 | 日本成人一区二区 | 成人精品一区二区三区中文字幕 | 羞羞网站视频 |