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
Stream<T> filter(Predicate<? super T> predicate);
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
<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的方法。
筆者傳入是toList()方法。把最後數據變成一個集合。這個方法是Collectors類的一個靜態方法。固然Collectors類裏面有不少靜態方法。若是大家去看一下他的代碼。你就會發現他的方法名字好像都是在對數據操做的樣子。沒有錯。之後咱們開發過程都會用到Collectors類的方法集。
記得引用下面代碼
import static java.util.stream.Collectors.toList;
從上面的幾個例子來看。讓筆者感受以下
那麼其餘呢?好比 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語句的功能很像呢?以下
理解了上面代碼的基礎用法的概念以後,咱們接下要一步步去看看JAVA8流的思想。