JAVA8給我帶了什麼——流(入門)

JAVA8有一個新功能——流。筆者簡單的看一下流。而後默默的閉上眼睛。感嘆一聲:這不是.NET裏面的Linq嗎?若是大家當中有誰作過.NET程序員的話,對於流的學習其實幫助是很大的。可是要明白你如今是在學JAVA的流。雖然他們的概念是有一點像。但是這也只是對你在理解流上面有必定的幫助。由於JAVA實現的方式卻完成不同子(不入流程序員的我的理解)。java

好吧。那麼流是什麼呢?若是用書裏面的方式解釋的話,筆者可能也看不懂。作過開發的人員通常都會知道一些SQL語句吧,SELECT語句這個功能。相信你們必定都熟悉吧——SELECT是對數據庫的數據進行操做。一樣子JAVA也有數據啊。好比集合、數組。那麼爲何JAVA不可能實現一套代碼式的數據操做。若是這樣子不知道你們會不會明白呢?(固然這不是官方,是不入流的程序員這樣了理解的)
SQL語句裏面有什麼——SELECT、FORM、WHERE、ORDER BY、GROUP BY。這些都是對數據庫裏面數據操做的常規動做。JAVA8的流呢? 即然是流。那麼說明必須把對應的數據變成一個流才行。關鍵方法stream()就是這個做用。 舉例子來講明吧。筆者有一組字符數組,筆者相要查找出有含有 r 的字符。程序員

 1 package com.aomi;
 2 
 3 import java.util.Arrays;
 4 import java.util.List;
 5 
 6 public class Main {
 7 
 8     public static void main(String[] args) {
 9         // TODO Auto-generated method stub
10 
11         List<String> datas = Arrays.asList("red", "green", "bule");
12 
13         datas
14         .stream()
15         .filter(s -> s.contains("r"))
16         .forEach(s -> System.out.println(s));
17     }
18 
19 }

運行結果:數據庫

讓咱們想一想若是是之前的話,要什麼樣子去實現呢?數組

 1 package com.aomi;
 2 
 3 import java.util.ArrayList;
 4 import java.util.Arrays;
 5 import java.util.List;
 6 
 7 public class Main {
 8 
 9     public static void main(String[] args) {
10         // TODO Auto-generated method stub
11 
12         List<String> datas = Arrays.asList("red", "green", "bule");
13 
14 //        datas
15 //        .stream()
16 //        .filter(s -> s.contains("r"))
17 //        .forEach(s -> System.out.println(s));
18 
19         List<String> vDatas = new ArrayList<>();
20 
21         for (String str : datas) {
22             if (str.contains("r")) {
23                 vDatas.add(str);
24             }
25         }
26 
27         for (String str : vDatas) {
28             System.out.println(str);
29         }
30 
31     }
32 
33 }

相對之前來說很直觀表現代碼的意思。同時代碼量又小不少。app

  • filter:用於過濾數據的,從下面的代碼就能夠明白,返回一個boolean型類的結果。
Stream<T> filter(Predicate<? super T> predicate);
  • forEach:循環遍歷回來的結果集合。代碼看完就知道什麼樣子用了。
 void forEach(Consumer<? super T> action);

JAVA的代不少都是很人性化的,因此只要從名字就能夠明白他大概的功能了。函數

好了,筆者忽然有一個想法——想要把時面的‘r’字符變成‘o’字符。學習

 1 package com.aomi;
 2 
 3 import java.util.Arrays;
 4 import java.util.List;
 5 
 6 public class Main {
 7 
 8     public static void main(String[] args) {
 9         // TODO Auto-generated method stub
10 
11         List<String> datas = Arrays.asList("red", "green", "bule");
12 
13         datas.stream()
14         .map(s -> s.replace('r', 'o'))
15         .forEach(s -> System.out.println(s));
16 
17     }
18 
19 }

筆者去掉了filter方法,用了map。運行結果:this

  • map:至關於SQL中的 SELECT關鍵字有一點像。用於把結果變成你但願的樣子。看一下代碼
 <R> Stream<R> map(Function<? super T, ? extends R> mapper);

是一個function的函數式接口。函數描述符:T -> R。
顯示這樣子的例子有一點簡單。在實際的開發過程當中咱們每每都是一大波數據對象。這樣子筆者定義一個學生類。spa

package com.aomi;

public class Student {
    private String name;
    private int Sex;
    private String phone;
    private int score;
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getSex() {
        return Sex;
    }
    public void setSex(int sex) {
        Sex = sex;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    public int getScore() {
        return score;
    }
    public void setScore(int score) {
        this.score = score;
    }
    
    
}

在來寫一個數據源吧。3d

 1 package com.aomi;
 2 
 3 import java.util.ArrayList;
 4 import java.util.Arrays;
 5 import java.util.List;
 6 
 7 public class Main {
 8 
 9     public static List<Student> getSources()
10     {
11         List<Student> students =new ArrayList<>();
12         
13         Student stu1 = new Student();
14         
15         stu1.setName("lucy");
16         stu1.setSex(0);
17         stu1.setPhone("13700227892");
18         stu1.setScore(9);
19         
20         Student stu2 = new Student();
21         stu2.setName("lin");
22         stu2.setSex(1);
23         stu2.setPhone("15700227122");
24         stu2.setScore(9);
25         
26         Student stu3 = new Student();
27         stu3.setName("lili");
28         stu3.setSex(0);
29         stu3.setPhone("18500227892");
30         stu3.setScore(8);
31         
32         Student stu4 = new Student();
33         
34         stu4.setName("dark");
35         stu4.setSex(1);
36         stu4.setPhone("16700555892");
37         stu4.setScore(6);
38         
39         
40         students.add(stu1);
41         students.add(stu2);
42         students.add(stu3);
43         students.add(stu4);
44         
45         return students;
46     }
47 
48 }

筆者定義了四個學生。這樣子時候筆者想看看學分(Score)大於6同窗的名字有哪一些。從上面代碼咱們能夠看到除了第四個同窗drak以後,其餘都是合格的。 讓咱們看一下代碼

 1 package com.aomi;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 import static java.util.stream.Collectors.toList;
 6 
 7 public class Main {
 8 
 9     public static void main(String[] args) {
10         // TODO Auto-generated method stub
11 
12         List<Student> stus = getSources();
13 
14         List<String> names = stus.stream()
15                 .filter(stu -> stu.getScore() > 6)
16                 .map(stu -> stu.getName())
17                 .collect(toList());
18 
19         for (String name : names) {
20             System.out.println(name);
21         }
22 
23     }
24 
25     public static List<Student> getSources() {
26         List<Student> students = new ArrayList<>();
27 
28         Student stu1 = new Student();
29 
30         stu1.setName("lucy");
31         stu1.setSex(0);
32         stu1.setPhone("13700227892");
33         stu1.setScore(9);
34 
35         Student stu2 = new Student();
36         stu2.setName("lin");
37         stu2.setSex(1);
38         stu2.setPhone("15700227122");
39         stu2.setScore(9);
40 
41         Student stu3 = new Student();
42         stu3.setName("lili");
43         stu3.setSex(0);
44         stu3.setPhone("18500227892");
45         stu3.setScore(8);
46 
47         Student stu4 = new Student();
48 
49         stu4.setName("dark");
50         stu4.setSex(1);
51         stu4.setPhone("16700555892");
52         stu4.setScore(6);
53 
54         students.add(stu1);
55         students.add(stu2);
56         students.add(stu3);
57         students.add(stu4);
58 
59         return students;
60     }
61 
62 }

運行結果:

當咱們看到這個例子的時候,咱們就能夠肯定map是作什麼。就是用於最後肯定返回數據類型。在這個代碼中。筆者又用到了一個叫collect的方法。

  • collect:用於收集數據的功能。便是把相關的數據彙總成爲另外一種數據。

筆者傳入是toList()方法。把最後數據變成一個集合。這個方法是Collectors類的一個靜態方法。固然Collectors類裏面有不少靜態方法。若是大家去看一下他的代碼。你就會發現他的方法名字好像都是在對數據操做的樣子。沒有錯。之後咱們開發過程都會用到Collectors類的方法集。
記得引用下面代碼

import static java.util.stream.Collectors.toList;

 從上面的幾個例子來看。讓筆者感受以下

  • stream相關於SQL裏面的FROM
  • filter至關於SQL裏面的WHERE.
  • map至關於SQL裏面的SELECT

那麼其餘呢?好比 order by或 group by 。讓咱們接着看吧。

如今筆者想在按學分(Score)高到低排序而且只顯示學生名和學分呢?

package com.aomi;

import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.toList;

import java.util.ArrayList;
import java.util.List;

public class SMain {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        List<Student> stus = getSources();

        List<String> names = stus.stream() .sorted(comparing(Student::getScore).reversed()) .map(stu -> "學名:"+stu.getName()+"  學分:"+stu.getScore()) .collect(toList()); 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;
    }
}

運行結果:

關於上面sorted的用法。筆者上面已經講過了。
如今筆者想看看男女各位的學習狀況。又要如何。來分個組吧。

 1 package com.aomi;
 2 
 3 import static java.util.stream.Collectors.groupingBy;
 4 
 5 import java.util.ArrayList;
 6 import java.util.List;
 7 
 8 public class SMain {
 9 
10     public static void main(String[] args) {
11         // TODO Auto-generated method stub
12 
13         List<Student> stus = getSources();
14 
15         stus.stream()
16         .collect(groupingBy(ss -> ss.getSex())).
17         forEach((Integer sex, List<Student> students) -> {
18             System.out.println("sex:" + sex);
19 
20             for (Student student : students) {
21                 System.out.println("name:" + student.getName() + "  score:" + student.getScore());
22             }
23         });
24 
25     }
26 
27 //去掉學生源的方法。太多了影響查看
28 }

結果:

即然都分組了。那就筆者在作一個業務。查看男女個組的人數。

package com.aomi;

import static java.util.stream.Collectors.groupingBy;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class SMain {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        List<Student> stus = getSources();

        stus.stream().collect(groupingBy(ss -> {
            if (ss.getSex() == 0)
                return "女";
            else
                return "男";
        }, Collectors.counting()))
        .forEach((String sex, Long count) -> {
            System.out.println("sex:" + sex + "  count:" + count);

        });

    }
......
.....//去掉數據源
.....

}

運行結果:

在來一個分組以後,男女個組的總分。

package com.aomi;

import static java.util.stream.Collectors.groupingBy;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class SMain {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        List<Student> stus = getSources();

        stus.stream().collect(groupingBy(ss -> {
            if (ss.getSex() == 0)
                return "女";
            else
                return "男";
        }, Collectors.summingLong(t -> t.getScore())))
        .forEach((String sex, Long sum) -> {
            System.out.println("sex:" + sex + "  count:" + sum);

        });

    }

    。。。。。
}

運行結果:

經過這倆個例子,咱們就能夠明白一個道理。groupingBy的第二個參數,是一個任何型類的收集器。也就是說分組以後,你能夠在進行對分組以後的結果進處理。

好了。大家有沒有感受跟SQL語句的功能很像呢?以下

  • stream相關於SQL裏面的FROM
  • filter至關於SQL裏面的WHERE.
  • map至關於SQL裏面的SELECT
  • sorted至關於SQL裏面的Order BY
  • Collectors.groupingBy至關於SQL裏面的GROUP BY
  • Collectors.summingLong至關於SQL裏面的SUM函數。只不過他又加了一步結果轉爲Long類型
  • Collectors.counting至關於SQL裏面的COUNT函數

 理解了上面代碼的基礎用法的概念以後,咱們接下要一步步去看看JAVA8流的思想。

相關文章
相關標籤/搜索