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.實例