在之前的工做中,業務中不少時候是須要循環來獲取某一個列表中的一些數據,好比獲取某一個值作業務邏輯的判斷,或者獲取其中一部分的數據,如使用狀態的標誌位等等,這個時候可能不少時候都是使用簡單的for循環、Foreach循環或者迭代器等方式,不少時候爲了處理業務都是須要循環嵌套循環的。可是在Java8中爲集合的相關處理提供了一個更強大的工具,那麼就是Stream,在瀏覽代碼的時候看見了其餘人的書寫,感受很驚奇(此時本身也很無語,Java8出來這麼久了,本身好像好沒有意識到它到底添加了那些新的內容,有什麼新的特性,簡化了那些操做等等),因此本身就對這個東西充滿了好奇。數組
它是Java8 API添加的一個新的抽象流,它把要處理的元素看作一種流,流在管道中傳輸,而且能夠在管道的節點上進行處理,例如排序,篩選和聚合等操做,可讓人以一種聲明的方式來處理數據。
元素流在管道中通過中間操做(intermediate operation)處理,最後由最終操做(terminal operation)獲得前面的處理結果。ide
+------------------------+ +---------+ +-----------+ +--------+ +-------+
| stream of elements +--------> |filter +-----> |sorted +-----> |map +----> |collect|
+-----------------------+ +---------+ +-----------+ +--------+ +-------+工具
stream是一個來自數據源的元素隊列並支持聚合操做:
(1)元素是特定的元素,造成一個隊列,可是stream不會存儲元素,而是按需計算
(2)數據源能夠是集合、數組、I/Ochannel等
(3)集合操做相似鏈式的SQL,如filter、map、reduce、find、match、sortde等this
使用stream方式,爲集合建立串行流spa
使用parallelStream 爲集合建立並行流code
Stream提供了新的方法來迭代流中的每個數據blog
public class StreamDemoTest { private final static Integer MAX_CIRCLE = 100; public static void main(String[] args) { List<Integer> strList = new ArrayList<>(); Map<Integer, String> integerMap = new HashMap<>(); for (int i = 0; i < MAX_CIRCLE; i++) { strList.add(i); integerMap.put(i, i+"e"); } strList.stream().forEach(s -> System.out.println(s)); } }
map方法用於映射每一個元素到對應的結果排序
public class StreamDemoTest { private final static Integer MAX_CIRCLE = 100; public static void main(String[] args) { List<Integer> strList = new ArrayList<>(); Map<Integer, String> integerMap = new HashMap<>(); for (int i = 0; i < MAX_CIRCLE; i++) { strList.add(i); integerMap.put(i, i+"e"); } //strList.stream().forEach(s -> System.out.println(s)); List<Integer> integerList = strList.stream().map(i -> i * i).collect(Collectors.toList()); integerList.stream().forEach(s -> System.out.println(s)); } }
filter用於經過設置的條件過濾出元素繼承
List<String> stringList = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); // 獲取空字符串的數量 long count = stringList.stream().filter(string ->string!="abc").count(); //獲取不是abc和空的字符串 List<String> list = stringList.stream().filter(str -> str != "abc"&&str!="").collect(Collectors.toList());
用於獲取指定數量的流隊列
List<String> stringList = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); // 獲取空字符串的數量 long count = stringList.stream().filter(string ->string!="abc").count(); //限定獲取過濾條件後的數量 List<String> list = stringList.stream().filter(str -> str != "abc"&&str!="").limit(3).collect(Collectors.toList()); list.stream().forEach(s-> System.out.println(s));
limit的位置能夠在filter前面或者後面,只是表示的含義不同而已。
sorted用於對流進行排序
public static void main(String[] args) { List<String> strList = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); //天然排序 System.out.println("天然排序"); strList.stream().sorted().forEach(s -> System.out.println(s)); System.out.println("倒序排序"); strList.stream().sorted(Comparator.reverseOrder()).forEach(s -> System.out.println(s)); }
輸出結果已經按照要求進行了排序,默認的是升序排列了,若是想簡單的倒序排序,可使用 Stream<T> sorted(Comparator<? super T> comparator)方法,裏面採用Comparator.reverseOrder()進行倒序排序。
若是是自定義的其餘的類型,怎麼進行排序那?
下面是自定義的一個用戶信息的簡單實體
class User { /** * 姓名 **/ private String userName; /** * 英文名稱 **/ private String englishName; /** * 年齡 **/ private int age; /** * 住址 **/ private String address; /** * 電話 **/ private String tel; public User(String userName, String englishName, int age) { this.userName = userName; this.englishName = englishName; this.age = age; } public User(String userName, String englishName, int age, String address, String tel) { this.userName = userName; this.englishName = englishName; this.age = age; this.address = address; this.tel = tel; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getEnglishName() { return englishName; } public void setEnglishName(String englishName) { this.englishName = englishName; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getTel() { return tel; } public void setTel(String tel) { this.tel = tel; } @Override public String toString() { return "User{" + "userName='" + userName + '\'' + ", englishName='" + englishName + '\'' + ", age=" + age + ", address='" + address + '\'' + ", tel='" + tel + '\'' + '}'; } }
public static void main(String[] args) { /* List<String> strList = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); //天然排序 System.out.println("天然排序"); strList.stream().sorted().forEach(s -> System.out.println(s)); System.out.println("倒序排序"); strList.stream().sorted(Comparator.reverseOrder()).forEach(s -> System.out.println(s));*/ List<User> userList = new ArrayList<>(); User user = new User("Angle", "B", 10); userList.add(user); user = new User("Heni", "G", 39); userList.add(user); user = new User("Eson", "F", 6); userList.add(user); user = new User("Cily", "D", 2); userList.add(user); user = new User("Cily", "G", 6); userList.add(user); user = new User("Eson", "G", 6); userList.add(user); System.out.println("正常輸出"); userList.stream().forEach(s-> System.out.println(s.toString())); System.out.println("按照名稱默認升序排列"); userList.stream().sorted(Comparator.comparing(User::getUserName)).forEach(s -> System.out.println(s)); System.out.println("按照名稱進行倒序排列"); userList.stream().sorted(Comparator.comparing(User::getUserName).reversed()).forEach(s -> System.out.println(s)); System.out.println("多元素排列"); userList.stream().sorted(Comparator.comparing(User::getUserName).thenComparing(User::getAge).reversed()).forEach(s -> System.out.println(s)); System.out.println("轉換爲map"); userList.stream().collect(Collectors.toMap(User::getUserName,User::getAge,(newValue,oldValue)->newValue)).entrySet().stream().forEach(e-> { System.out.println(e.getKey()+"====="+e.getValue()); }); System.out.println("過濾之後的"); userList.stream().filter(e -> e.getUserName().equals("Eson")).sorted(Comparator.comparing(User::getAge).reversed()) .forEach(e -> System.out.println(e.getUserName() + "======" + e.getAge())); System.out.println("若是是重複的key,值轉爲list"); Map<String, List<String>> map = userList.stream().collect(Collectors.toMap(User::getUserName,p->{ List<String> ageList = new ArrayList<>(); ageList.add(p.getAge() + ""); return ageList; },(List<String> valueNew,List<String> valueOld)->{ valueNew.addAll(valueOld); return valueNew; })); map.entrySet().stream().forEach(e-> { System.out.println(e.getKey()+"====="+e.getValue()); }); }
輸出結果:
正常輸出 User{userName='Angle', englishName='B', age=10, address='null', tel='null'} User{userName='Heni', englishName='G', age=39, address='null', tel='null'} User{userName='Eson', englishName='F', age=6, address='null', tel='null'} User{userName='Cily', englishName='D', age=2, address='null', tel='null'} User{userName='Cily', englishName='G', age=6, address='null', tel='null'} 按照名稱默認升序排列 User{userName='Angle', englishName='B', age=10, address='null', tel='null'} User{userName='Cily', englishName='D', age=2, address='null', tel='null'} User{userName='Cily', englishName='G', age=6, address='null', tel='null'} User{userName='Eson', englishName='F', age=6, address='null', tel='null'} User{userName='Heni', englishName='G', age=39, address='null', tel='null'} 按照名稱進行倒序排列 User{userName='Heni', englishName='G', age=39, address='null', tel='null'} User{userName='Eson', englishName='F', age=6, address='null', tel='null'} User{userName='Cily', englishName='D', age=2, address='null', tel='null'} User{userName='Cily', englishName='G', age=6, address='null', tel='null'} User{userName='Angle', englishName='B', age=10, address='null', tel='null'} 多元素排列 User{userName='Heni', englishName='G', age=39, address='null', tel='null'} User{userName='Eson', englishName='F', age=6, address='null', tel='null'} User{userName='Cily', englishName='G', age=6, address='null', tel='null'} User{userName='Cily', englishName='D', age=2, address='null', tel='null'} User{userName='Angle', englishName='B', age=10, address='null', tel='null'}
能夠看出來,整個排序是至關的簡單了,不須要本身的類繼承comparable,也不須要本身擴展排序comparator了。
對於map類型格式的數據。能夠對鍵排序或者值排序
1 public static void main(String[] args) { 2 Map<String, String> map = new LinkedHashMap<String, String>(); 3 map.put("12", "ddd"); 4 map.put("23", "eee"); 5 map.put("34", "ddw"); 6 map.put("21", "ecc"); 7 8 System.out.println("根據值排序"); 9 map.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getValue)).forEach(e -> { 10 String key = e.getKey(); 11 String value = e.getValue(); 12 System.out.println("鍵值"+key+"值"+value); 13 }); 14 System.out.println("根據鍵排序"); 15 map.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getKey)).forEach(e -> { 16 //System.out.println(e.toString()); 17 String key = e.getKey(); 18 String value = e.getValue(); 19 System.out.println("鍵值"+key+"值"+value); 20 }); 21 }
輸出的結果:
根據值排序
鍵值12值ddd
鍵值34值ddw
鍵值21值ecc
鍵值23值eee
根據鍵排序
鍵值12值ddd
鍵值21值ecc
鍵值23值eee
鍵值34值ddw
綜合看下來,使用對應的Stream比使用日常簡單的循環而言代碼量少了不少。