文章參考自博客:https://www.cnblogs.com/franson-2016/p/5593080.html
以及學習網站:how2java.cn
1.傳統方式和聚合操作遍歷數據的不同
傳統遍歷List的方式如下:
for(Hero h:list){ if(h.getAge()>50 && h.getId()<400) System.out.println(h.getName()); }
而使用了聚合操作的方式如下:
list .stream() .filter( h-> h.getAge()>50 && h.getId()<400) .forEach(h-> System.out.println(h.getName()));
2.Stream(流)是什么?
Stream是對集合的包裝,通常和lambda一起使用。 使用lambdas可以支持許多操作,如 map, filter, limit, sorted, count, min, max, sum, collect 等等。 同樣,Stream使用懶運算,他們並不會真正地讀取所有數據,遇到像getFirst() 這樣的方法就會結束鏈式語法。
Stream和Collection結構化的數據不同,Stream有一系列的元素
管道指的是一系列的聚合操作的總和
管道由三部分組成:管道源,中間操作,結束操作
(1)管道源: 其可以是一個集合,一個數組,一個生成器函數或一個I / O通道
//管道源是一個集合 list .stream() .forEach(h-> System.out.println(h.getName())); //管道源是一個數組 Hero array[] = list.toArray(new Hero[list.size()]); Arrays.stream(array) .forEach(h-> System.out.println(h.getName()));
(2)零個或多個中間操作: 每個中間操作會返回一個流,如filter,中間操作時懶操作,不會真正遍歷
中間操作有很多種,主要分為兩種:
1.對元素進行篩選:filter(匹配),distinct(去除重復),sorted(自然排序)
sorted(Comparator)(指定排序),limit(保留),skip(忽略)
2.轉為其他形式的流:mapToDouble(轉為double的流), map(轉換為任意類型的流)
(3)結束操作: 例如forEach,會返回非流結果,例如基本類型的值(int,float,double)、對象或者集合,或者在終端操作為forEach的情況下沒有返回值。
結束操作時才真正進行遍歷行為,前面的中間操作也在這個時候真正的執行。
常見的結束操作如下:
forEach()(遍歷每個元素),toArray()(轉換為數組),min(Comparator)(取最小的元素)
max(Comparator)(取最大的元素),count()(總數),findFirst()(第一個元素)
3.具體用例
首先創建一個100個元素的表,用隨機數填充其年齡和ID
Random r = new Random(System.currentTimeMillis()); List<Hero> list = new ArrayList<>(); for (int i = 0; i < 100; i++) { list.add(new Hero("hero-"+i,r.nextInt(500),r.nextInt(100))); }
然后執行各種中間操作:
//用filter篩選滿足條件的對象,並進行操作 list .stream() .filter(h-> h.getId()<300 && h.getAge()>50) .forEach(h-> System.out.println(h)); //用distinct去除重復元素 list .stream() .distinct() .forEach(h-> System.out.print(h)); //用sorted進行排序 list .stream() .sorted((h1,h2) -> h1.getAge()>h2.getAge() ? 1:-1) .forEach(h-> System.out.println(h)); //用limit保留三個元素 list .stream() .limit(3) .forEach(h-> System.out.println(h)); //用skip忽略前三個元素 list .stream() .skip(3) .forEach(h-> System.out.println(h)); //用mapToDouble轉換為Double的Stream list .stream() .mapToDouble(Hero::getAge) .forEach(h-> System.out.println(h)); //轉換為任意類型的Stream list .stream() .map((h)-> h.getName()+"-"+h.getAge()+"-"+h.getId()) .forEach(h-> System.out.println(h));
終端操作(結束操作)的用例如下:
//用forEach遍歷集合 list .stream() .forEach(h-> System.out.println(h)); //用toArray將表變為數組 Object[] arrays = list .stream() .toArray(); //用min得到最小值 Hero h1 = list .stream() .min((hf,hs)->hf.getAge()-hs.getAge()) .get(); //用max得到最大值 Hero h2 =list .stream() .max((hf,hs) -> hf.getAge()-hs.getAge()) .get(); //用count計算流中的數據總數 long count = list .stream() .count(); //用findFirst得到第一個元素 Hero h3 = list .stream() .findFirst() .get();
測試用例:
Hero h = list .stream() .sorted((h1,h2)-> h1.getAge()>h2.getAge() ? -1:1) .skip(2) .findFirst() .get();