Java8特性----lambda表示式之Collection常見操作
現在越來越多的公司開始使用jdk8了,jdk8有許多新特性,其中一個特性便是流式處理,進而有好多對於集合的便利操作
我自己也是剛開始熟悉jdk8,便在此記錄一些基本的關於集合的操作 至於一些理論上的東西我就不寫了,某度一大堆,因為一點點介紹每段的含義來路也不是一篇部落格就能寫完的,我只會簡單說一下每段的意思,廢話不多說,上程式碼
先建立一下的練習會用到的類
package com.chunying.lambda; /** * @author chunying */ public class Student { private finalString name; private final Integer age; private final Gender gender; public Student(String name, Integer age , Gender gender) { this.name = name; this.age = age; this.gender = gender; } public String getName() { return name; } public IntegergetAge() { return age; } public Gender getGender() { return gender; } public enum Gender{MALE , FEMALE}; }
package com.chunying.lambda; import java.util.Arrays; import java.util.List; /** * @author chunying */ public class LambdaDemo { List<Student> data= Arrays.asList( new Student("張三" ,23 , Student.Gender.MALE), new Student("李四" ,24 , Student.Gender.MALE), new Student("王五" ,24 , Student.Gender.FEMALE), new Student("趙六" ,23 , Student.Gender.FEMALE) ); }
這裡我建立了一個學生類以及學生類的集合,以下的所有操作都將通過它們來完成
首先第一個:獲取所有男性的學生集合
如果沒有jdk8我們會怎樣寫呢?
@Test public void fun1() { //所有男性集合 List<Student> result = new ArrayList<>(); for(Student student : data) { if(student.getGender().equals(Student.Gender.MALE)) { result.add(student); } } System.out.println(result); }
需要遍歷集合,一個一個去判斷是否符合我們的條件,如果資料量比較大,或者判斷條件比較多,那麼可能在單執行緒情況下就會比較慢。多執行緒:就要和synchronized打交道,煩不勝煩,一不注意沒處理好就會出問題
jdk8幫我們解決了這個問題
我們先看程式碼
@Test public void fun2() { List<Student> result = data.stream() .filter(student -> student.getGender().equals(Student.Gender.MALE)) .collect(Collectors.toList()); System.out.println(result); }
首先lambda表示式的基礎我就不說了,我會在其他文章補充,這裡不是重點,這個結果和上面是一樣的
首先stream()方法,將集合變成了流,
fileter()方法,過濾到我們所需要的,
最後collect(Collectors.toList())將得到的流物件轉換為集合。
第二個:將所有的學生按照年紀分組,並且獲取到所有的年紀的集合
首先還是看沒有jdk8怎麼做
@Test public void fun3() { List<Integer> allAges = new ArrayList<>(); Map<Integer , List<Student>> studentByAge = new HashMap<>(); for(Student student : data) { Integer age = student.getAge(); if(!allAges.contains(age)) { allAges.add(age); } List<Student> temp = studentByAge.get(age); if(temp == null) { temp = new ArrayList<>(); temp.add(student); studentByAge.put(age , temp); }else { temp.add(student); } } System.out.println(allAges); System.out.println(studentByAge); }
其中temp集合是完全沒有用的中間計算集合。非常麻煩而且不易讀
我們看jdk8怎麼做
@Test public void fun4() { List<Integer> allAges = data.stream().map(Student::getAge) .distinct() .collect(Collectors.toList()); Map<Integer , List<Student>> studentByAge = data.stream().collect(Collectors.groupingBy(Student::getAge)); System.out.println(allAges); System.out.println(studentByAge); }
先看獲取年紀,通過map()方法獲取到所有的年紀,distinct()去重,collect轉換成集合
分組這邊,比較上面這裡僅僅一行程式碼,通過groupingBy()把所有的學生按照年紀分組即可。
第三個:所有學生按照姓名分組(假設沒有重名的)
首先還是看沒有jdk8怎麼做。
@Test public void fun5() { Map<String , Student> studentByName = new HashMap<>(); for(Student student : data) { studentByName.put(student.getName() , student); } }
接下來看jdk8
@Test public void fun6() { Map<String , Student> studentByName = data.stream().collect(Collectors.toMap(Student::getName , student->student)); }
這裡用到了toMap()方法,不多解釋了
第四個:集合遍歷
jdk8之前集合遍歷,單列集合都可以通過for(Object o : data){}來遍歷,底層無非還是iterator。
map就麻煩了,一種是通過拿到keySet再去拿每一個值,一種是通過entrySet拿到每一個entry物件,再去獲取鍵值。操作很不方便
直接看jdk8的結合遍歷
@Test public void fun6() { Map<String , Student> studentByName = data.stream().collect(Collectors.toMap(Student::getName , student->student)); data.forEach(student -> { System.out.println(student); }); studentByName.forEach((name , student)-> { System.out.println(name + "-" + student); }); }怎麼樣是不是方便了很多?
第五個:排序以及型別轉換
jdk8以前的排序大多是通過Comparator來排序,每次要定義排序規則或者比較器,很不方便
我們看jdk8
@Test public void fun7() { //將所有學生按照年級排序並返回學生集合 List<Student> result = data.stream() .sorted(Comparator.comparing(Student::getAge)) .collect(Collectors.toList()); System.out.println(result); }
是不是很方便的。
常用的操作就這些,我就先記錄到這裡。