1. 程式人生 > 程式設計 >Java Stream 流的使用過程解析

Java Stream 流的使用過程解析

1. 篩選和切片

用謂詞篩選

filter方法接受一個返回boolean的方法。

List<Dish> vegetarianMenu=menu.stream().filter(Dish::isVegetarian) .collect(toList());

distinct去重

distinct方法,根據流中元素的hashCode和equals方法。例:

List<Integer> numbers = Arrays.asList(1,2,1,3,4); 
numbers.stream().filter(i -> i % 2 == 0).distinct().forEach(System.out::println);

截短流

limit(n)方法,該方法會返回一個不超過給定長度的流。

如果流是有序的,則最多會返回前n個元素。

limit也可以用在無序流上,比如源是一個Set。這種情況下,limit的結果不會以任何順序排列。

List<Dish> dishes = menu.stream() .filter(d -> d.getCalories() > 300).limit(3).collect(toList());

跳過元素

skip(n)方法返回一個扔掉了前n個元素的流。如果流中元素不足n個,則返回一個空流。skip方法和limit方法可以看成是相反的操作。

2. 對映

簡單對映

流支援map方法,它會接受一個函式作為引數。這個函式會被應用到每個元素上,並將其對映成一個新的元素。

下面的程式碼,對words中的所有字串應用String::length方法。

List<String> words = Arrays.asList("Java 8","Lambdas","In","Action"); 
List<Integer> wordLengths = words.stream().map(String::length).collect(toList());

流的扁平化

什麼叫扁平化?舉個例子:把Stream<Stream< String >> 變成 Steam< String > 就叫扁平化。

一言以蔽之,flatmap方法讓你把一個流中的每個值都換成另一個流,然後把所有的流連線起來成為一個流。

    List<String> words = Arrays.asList("Java 8","Action");
    //map函式中每個字串都被切割為字串陣列,返回一個字串陣列的流
    List<String[]> collect = words.stream()
        .map(word -> word.split(""))
        .distinct()
        .collect(toList());
    //Arrays.stram方法接受一個數組返回一個流
    String[] arrayOfWords = {"Goodbye","World"};
    Stream<String> streamOfwords = Arrays.stream(arrayOfWords);

    //第一個map返回一個字串流,流中的元素是一個個的字串陣列。
    //第二個map對每一個字元陣列應用Arrays.stream函式,所以每一個字     //符串陣列對映為一個字串流。
    List<Stream<String>> collect1 = words.stream()
        .map(word -> word.split(""))
        .map(v -> Arrays.stream(v))
        .distinct()
        .collect(toList());
    //第一個map返回一個字串流,流中的元素是一個個的字串陣列。
    //flatMap方法把流中的每個字串陣列都換成一個流,然後連線它們成    //為一個流
    List<String> uniqueCharacters =
        words.stream()
            .map(w -> w.split(""))
            .flatMap(Arrays::stream)
            .distinct()
            .collect(Collectors.toList());

3. 查詢和匹配

另一個常見的資料處理套路是看看資料集中的某些元素是否匹配一個給定的屬性。Stream API通過allMatch、anyMatch、noneMatch、findFirst、findAny方法提供了這樣的工具。

注:這些工具方法的返回值都不是流。所以它們是終端操作

檢查謂詞是否至少匹配一個元素

if(menu.stream().anyMatch(Dish::isVegetarian)){ 
 System.out.println("The menu is (somewhat) vegetarian friendly!!"); 
}

檢查謂詞是否匹配所有元素

//是否所有元素都匹配
boolean isHealthy = menu.stream().allMatch(d -> d.getCalories() < 1000);
//是否所有元素都 不 匹配
boolean isHealthy = menu.stream().allMatch(d -> d.getCalories() < 1000);

查詢元素

findAny方法將返回當前流中的任意元素。

Optional<Dish> dish = menu.stream().filter(Dish::isVegetarian).findAny();

Optional是什麼?

查詢第一個元素

List<Integer> someNumbers = Arrays.asList(1,5); 
//filter返回一個流,findfirst在該流中找第一個
Optional<Integer> firstSquareDivisibleByThree = 
 someNumbers.stream() 
 .filter(x -> x == 2) 
 .findFirst(); 

4. 歸約

歸約:將流中的元素相互結合起來,求一個值。比如學生是元素求分數最高的學生、分數是元素求某位同學的總分。

//求numbers中所有數值的集合
int product = numbers.stream().reduce(1,(a,b) -> a * b);

一個初始值,這裡是0;

一個BinaryOperator來將兩個元素結合起來產生一個新值,這裡我們用的是

lambda (a,b) -> a + b。

無初始值

reduce還有一個過載的變體,它不接受初始值,但是會返回一個Optional物件:

Optional sum = numbers.stream().reduce((a,b) -> (a + b));

小結

該篇對於流的使用,做了簡要的筆記。可以滿足大多數情況的需求。不要只是看看,不要只是做了筆記。這麼好用的api,趕緊用起來吧。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。