5.1 方法引用
Lambda 表達式有一個常見的用法;Lanbda 表達式經常 調用參數。比如想得到藝術家的姓名,Lambda 表達式如下:
artist -> artist.getName()
這鐘用法如此普遍,因此java8 提供了一個簡寫語法,叫做 方法引用。用于重寫上面的lambda 表達式:
Artist::getName
標準語法為:ClassNam::methodName。這是一種和lambda 表達式等價的一種結構,在需要時才會調用。凡是使用lambda 表達式的地方,就可以使用方法引用。
構造函數也有同樣的縮寫形式,例如創建一個Artist 對象:
Artist::new
5.2 元素順序
在一個有序集合中創建一個流時,流中的順序就按出現順序排列。比如List
如果集合本身就是無序的,由此生成的流也是無序的。比如HashSet
使用并行流時,forEach方法不能保證元素是按順序處理的,如果需要保證按順序處理,應該使用forEachOrdered 方法。
5.3 使用收集器
5.3.1 轉換成其他集合
可能會有這樣的情況,你希望使用一個特定的集合收集值,你可以指定該集合的類型。此時你可以使用toCollection 方法,它接受一個Supplier作為參數,來創建集合。例如:
stream.collect(Collectors.toCollection(TreeSet::new));
5.3.2 轉換成值
還可以利用收集器讓流生成一個值:
找出樂隊成員最多的樂隊:
public Optional<Artist> biggestGroup(Stream<Artist> artists){
? ? ? ? // return artists.max(Comparator.comparing(artist -> artist.getMembers().count()));
? ? ? ? return artists.collect(Collectors.maxBy(Comparator.comparing(artist -> ?
? ? ? ?artist.getMembers().count())));
}
找出一組專輯上曲目的平均數:
public double averageNumberOfTracks (List albums) {
?// ?return ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //albums.stream().mapToInt(album>album.getTrackList().size()).average().getAsDouble();
? ? ?return albums.stream().collect(Collectors.averagingInt(album->album.getTrackList().size()));
}
通過stream()方法讓集合生成流,然后通過collect 方法收集結果。
5.3.3 數據分塊
另一個常用的流操作是將其分成兩個集合。
partitioningBy() 方法使用一個Predicate對象判斷一個元素應該屬于哪個部分,并根據布爾值返回一個Map到列表。
public Map<boolean,List<Artist>> bandsAndSolo(){
? ? ? ? ? ?return artists.collect(Collectors.partitioningBy(artist->artist.isSolo())); ? ? ? ?
}
5.3.4 數據分組
數據分組是一種更自然的分割數據操作,與將數據分成true 和false不同,可以使用任意值對數據分組。
//使用主唱對專輯分組
public Map<Artist , List<Album>> albumsByArtist(Stream<Album> albums){
? ? ? ? ?return albums.collect(Collectors.groupingBy(Album::getMainMusician));?
}
5.3.5 字符串
使用Collectors.joining 收集流中的值,可以方便的從一個流中得到一個字符串,允許用戶提供分隔符,前綴和后綴。
String result = artists.stream().map(Artist::getName).collect(Collectors.joining("," , "[" ?,"]" ));
5.3.6 組合收集器
//使用收集器計算每個藝術家的專輯
public Map<Artist,Long> numberOfAlbums(Stream<Album> albums){
? ? return albums.collect(Collectors.groupingBy(Album::getMainMusician, Collectors.counting()));
}
groupingBy 先將元素分塊,每塊都與getMainMusician 提供的鍵值相關聯,然后使用下游收集器 收集每塊中的元素,最后將結果映射為一個Map。
//使用收集器求每個藝術家的專輯
public Map> nameOfAlbums(Streamalbums){
? ? ? ? return ?albums.collect (Collectors.groupingBy (Album::getMainMusician , Collectors.mapping (Album::getName, Collectors.toList())));
}
5.4 Map類的變化
原有的Map迭代方式:
Map <Artist,Integer> countOfAlbums = new HashMap<>();
for(Map.Entry<Artist,List<Album> entry: albumByArtist.entrySet()>){
? ? ? ? ?Artist artist = entry.getKey();
? ? ? ? ?List<Album> albums = entry.getVaue();
? ? ? ? ?countOfAlbums.put(artist,album.size());
}