從Java8開始,新增了一個java.util.stream
包,這個包下的類和接口用來處理集合中的元素,在這個包下面有一個Stream接口,咱們主要使用這個接口來對集合進行操做。java
首先來看下建立Stream有哪幾種方式。sql
使用Stream自帶的靜態方法生成Stream對象,常見的靜態方法有如下幾個:數組
如今來看下每一個靜態方法的做用iphone
Stream.of是由兩個重載方法組成,一個傳入單值,一個傳入數組函數
String[] arr = {"hello", "world"}; Stream streamArr = Stream.of(arr); String str = "hello world"; Stream streamSingle = Stream.of(str);
Stream.generate和Stream.iterate能夠用來生成具備多個元素的Stream,若是不加控制會一直生成下去,通常配合limit(n)使用學習
先來看下Stream.iteratecode
Stream<Integer> stream5 = Stream.iterate(0, n-> n+1) .limit(5); stream5.forEach(System.out::println);
打印對象
0 1 2 3 4
Stream.iterate方法第一參數設定一個初始值,第二個參數表示基於這個初始值,每次循環後返回一個新的值替換這個初始值。limit(5)表示循環5次結束,最後Stream中包含了5個元素。排序
再來看下Stream.generate接口
Stream.generate方法只有一個Supplier參數,意思是每次循環執行Supplier接口方法返回一個新的值,放入到Stream中,因爲Supplier是一個函數式接口,所以能夠直接寫成Lambda表達式
AtomicInteger i = new AtomicInteger(); Stream.generate(()-> { return i.getAndIncrement(); }) .limit(5) .forEach(System.out::println);
上面的代碼一樣打印0~4。
除了Stream靜態方法以外,還可使用Collection接口中的stream()方法來生成Stream對象。
Collection<String> list = Arrays.asList("hello", "world"); Stream streamList = list.stream();
同理,只要是Collection接口的子類或實現類均可以使用stream()方法。
Stream中的方法有不少,大體概括以下表格所示:
方法 | 方法參數 | 返回類型 | 描述 |
---|---|---|---|
filer | Predicate<T> | Stream<T> | 過濾數據 |
distinct | 無 | Stream<T> | 去重 |
map | Function<T, R> | Stream<R> | 返回新的數據 |
flatMap | Function<T, R> | Stream<T, Stream<R>> | 返回新的數據,並作扁平化處理 |
sort | Comparator<T> | Stream<T> | 對數據進行排序操做 |
limit | long | Stream<T> | 截取前幾條數據 |
skip | long | Stream<T> | 跳過幾條數據 |
anyMatch | Predicate<T> | boolean | 匹配任意一條數據,若是匹配到返回true |
noneMatch | Predicate<T> | boolean | 若是沒有匹配到數據,返回true |
allMatch | Predicate<T> | boolean | 若是全部數據所有匹配到,返回true |
findAny | 無 | Optional<T> | 返回任意一條數據 |
findFirst | 無 | Optional<T> | 返回第一條數據 |
count | 無 | long | 返回元素個數 |
forEach | Consumer<T> | void | 遍歷元素,執行Consumer |
collect | Collector<T, A, R> | R | 元素收集 |
reduce | BinaryOperator<T> | Optional<T> | 數據彙總 |
從方法的返回結果能夠看出,這些方法能夠分爲兩大類,一類是返回Stream對象,能夠繼續對Stream操做,這類方法也被稱之爲中間操做(Intermediate operations)
,另外一類是返回非Stream,結束操做,這類方法也被稱之爲中端操做(Terminal operations)
,這兩類方法每每一塊兒配合操做。
下面咱們挑選其中的幾個方法來演示它們的做用。
filter方法用來篩選出咱們想要的數據,方法參數是一個Predicate接口,由於Predicate是一個函數式接口,咱們可使用Lambda表達式來寫。
Integer[] arr = { 1, 2, 3, 4, 5 }; long count = Stream.of(arr) .filter(i -> i % 2 == 0) .count(); System.out.println("偶數數量:" + count);
在這個例子中,咱們篩選出了偶數數字,而且統計出偶數的數量。若是要打印每一個偶數,可使用forEach方法
Stream.of(arr) .filter(i -> i % 2 == 0) .forEach(System.out::println);
打印:
2 4
若是要查找任意一個元素,可使用findAny
int num = Stream.of(arr) .filter(i -> i % 2 == 0) .findAny() .orElse(0); System.out.println("findAny:" + num);
注意,findAny()返回的是一個Optional對象,由於有可能沒有找到數據,所以須要開發者本身處理沒有找到數據的狀況。同理findFirst
也是返回一個Optional對象。
distinct方法會對元素進行去重操做,相似於SQL中的SELECT distinct xx
Stream.of(1,1,2,3,3,4) .distinct() .forEach(System.out::println)
打印
1 2 3 4
使用sorted方法能夠對元素進行排序操做
Stream.of(6,1,7,2,8,5) .sorted() .forEach(System.out::println);
打印
1 2 5 6 7 8
sorted()默認是從小到大排列,若是要從大到小降序,可使用.sorted(Comparator.reverseOrder())
Stream.of(6,1,7,2,8,5) .sorted(Comparator.reverseOrder()) .forEach(System.out::println);
能夠看到,sorted方法容許傳入一個比較器Comparator
讓開發者本身實現排序邏輯。下面是一個自定義Comparator例子:
@Data @AllArgsConstructor static class Goods { private String goodsName; private int price; } Stream.of( new Goods("iphoneX", 4000) , new Goods("mate30 pro", 5999) , new Goods("redmek20", 2999) ) .sorted((goods1, goods2) -> { return Integer.compare(goods1.getPrice(), goods2.getPrice()); }) .forEach(System.out::println);
這個列子演示了按商品價格從低到高排序。此處的sorted部分能夠簡化爲:.sorted(Comparator.comparing(Goods::getPrice))
map方法能夠返回一個新的數據對象,組成一個新的Stream。
List<Goods> list = Arrays.asList( new Goods("iphoneX", 4000) , new Goods("mate30 pro", 5999) , new Goods("redmek20", 2999) ); list.stream() .map(goods -> goods.getGoodsName()) .forEach(System.out::println);
上面的示例演示的是從原有的商品對象中拿到商品名稱,而後組成一個新的List,其效果等同於
List<String> goodsNameList = new ArrayList<>(list.size()); for(Goods goods : list) { goodsNameList.add(goods.getGoodsName()); }
map方法通常配合collect()方法一塊兒使用
List<Goods> list = Arrays.asList( new Goods("iphoneX", 4000) , new Goods("mate30 pro", 5999) , new Goods("redmek20", 2999) ); List<String> nameList = list.stream() .map(goods -> goods.getGoodsName()) .collect(Collectors.toList());
collect(Collectors.toList())
的意思是將Stream中的元素轉換成List
flatMap()方法是map()方法的扁平化處理,與map不一樣的是,flatMap把返回Stream對象操做交給開發者本身處理。看下面的例子:
Stream<String[]> stream = Stream.of("I am Java", "hello world") .map(s -> s.split(" "));
這個例子的本意是想要將每一個字符串進行拆分,把單詞單獨放入到Stream中,因爲map返回的是一個字符串數組String[]
,所以獲得的Stream對象的泛型參數就是Stream<String[]>
,而不是Stream<String>
。
解決辦法是使用flatMap:
Stream<String> stream2 = Stream.of("I am Java", "hello world") .flatMap(s -> Stream.of(s.split(" "))); stream2.forEach(System.out::println);
打印:
I am Java hello world
下面來看一個綜合示例,演示的功能是:查詢商品名稱,價格大於3000,按價格降序
public class StreamTest3 { @Data @AllArgsConstructor static class Goods { private String goodsName; private int price; } public static void main(String[] args) { List<Goods> list = Arrays.asList( new Goods("iphoneX", 4000) , new Goods("mate30 pro", 5999) , new Goods("redmek20", 2999) ); // 查詢商品名稱,價格大於3000,按價格降序 List<String> nameList = list.stream() .filter(goods -> goods.getPrice() > 3000) .sorted(Comparator.comparing(Goods::getPrice).reversed()) .map(Goods::getGoodsName) .collect(Collectors.toList()); System.out.println(nameList); } }
打印:[mate30 pro, iphoneX]
代碼對應的SQL爲:
SELECT goods_name FROM goods WHERE price > 3000 ORDER BY price DESC
本篇講解了如何建立Stream以及Stream一些經常使用方法的使用方式,咱們將會在下一篇着重講解collect()
和reduce()
的用法。
按期分享技術乾貨,一塊兒學習,一塊兒進步!