聊一下Java8中的Stream

1.從外部迭代到內部迭代

外部迭代

for循環其實是封裝了一個迭代的語法糖

int count =0;
Iterator<Artist> iterator = allArtists.iterator;
while(iterator.hasNext()){
  Artist artist = iterator.next(); 
  if(artist.isForm("Cter")){
        count++;
  }
}

首先調用iterator方法 產生一個新的Iterador對象,近而控制整個迭代過程,這就是外部迭代。 

                                                   

 

內部迭代 

long count = allArtists.stream()
                       .filter(artist -> artist.isForm("Cter"))
                       .count();

                                                    

Stream 是用函數式編程方式在集合類上進行復雜操作的工具

2.實現機制

內部迭代的代碼中 整個過程被分解爲兩種更簡單的操作:過濾和計數 ,看似有化簡爲繁之嫌 與外部迭代的一次for循環相比 兩種操作是否意味着兩次循環? 其實不是 這只是一次循環

 

通常來說在java中調用一個方法 計算機會隨即執行操作 比如Syso(“hello world”) Stream裏面的一些方法卻略有不同。它們雖然是普通的java方法,但返回的stream對象卻不是一個新集合,而是創建新集合的配方。

allArtists.stream()
                       .filter(artist -> artist.isForm("Cter"));

這行代碼並沒有實際性的操作,filter只刻畫出了Stream,但沒有產生新的集合。像filter這樣只描述Stream,最終不產生新集合的方法叫做惰性求值方法;而像count這樣最終會從Stream產生值的方法叫做及早求值方法

看下面代碼

long count = allArtists.stream()
                       .filter(artist -> {
                            System.out.print("artist.getName()");
                            return artist.isForm("Cter")
                        });

運行這段代碼,程序不會輸出任何信息

如果將同樣的輸出語句加入一個擁有終止操作的流中,如下,藝術家的名字就會被輸出

long count = allArtists.stream()
                       .filter(artist -> {
                            System.out.print("artist.getName()");
                            return artist.isForm("Cter")
                        })
                       .count();

判斷惰性求值還是及早求值 只需要看它的返回值,如果返回值是Stream,那麼就是惰性求值;如果返回值是另一個值或者空,那麼就是及早求值

使用這些操作的理想方法就是形成一個惰性求值的鏈,最後用一個及早求值返回想要的結果,整個過程和構造者模式有共通之處。

3.常用的流操作

 

3.1 collect(toList())

      collect(toList()) 方法由Stream裏的值生成一個列表,是一個及早求值操作 

List<String> collected = Stream.of("a","b")
                               .collect(Collectors.toList());
assertEquals(Arrays.asList("a","b"),collectd);

 Stream 中of方法使用一組初始值生成新的Stream。

3.2 map

    如果有一個函數可以將一種類型的值轉換成另外一種類型,map操作就可以使用該函數,將一個流中的值轉換成一個新的流。

Lits<String> collected = new ArrayList<>();
for(String string:asList("a","b")){
    String uppercaseString = string.toUpperCase();
        collected.add(uppercaseString);
}

                                           

使用新的流框架將一組字符轉換成大寫形式

List<String> collected = Stream.of("a","b")
                               .map(string -> string.toUpperCase())
                               .collect(toList());

3.3 filter

遍歷數據並檢查其中的元素時

                                         

之前的形式

Lits<String> beginningWithNumbers= new ArrayList<>();
for(String string:asList("a","b")){
    if(isDigit(value.charAt(0))){
       beginningWithNumbers.add(string);
    }
}

使用filter

List<String> beginningWithNumbers= Stream.of("a","b")
                               .filter(string -> isDigit(value.charAt(0)))
                               .collect(toList());

3.4 flatMap

flatMap方法可用Stream替換值,然後將多個Stream連接成一個Stream

                                             

List<Integer> together= Stream.of(asList(1,2),asList(3,4))
                               .flatMap(numbers -> numbers.stream())
                               .collect(toList());

3.5 max和min

查找Stream中的最大元素和最小元素

Track shortestTrack = tracks.stream()
                            .min(Compartor.comparing(tarck -> track.getLength()))
                            .get();

3.6通用模式 reduce

reduce操作可以實現從一組值中生成一個值,在上面的例子中 count min max方法都是reduce操作。

reduce求和

int count = Stream.of(1,2,3)
                  .reduce(0,(acc,element) ->acc+element);

lambda表達式的返回值是最新的acc,是上一輪acc的值和當前元素相加的結果

展開reduce操作

BinaryOperator<Integer> accumulator = (acc,element) ->acc+element;
int count = accumulator.apply(
                accumulator.apply(
                    accumulator.apply(0,1),
                2),
3);

4.實例

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章