第五章 高级集合类和收集器

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 biggestGroup(Stream 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> bandsAndSolo(){

           return artists.collect(Collectors.partitioningBy(artist->artist.isSolo()));        

}


5.3.4 数据分组

数据分组是一种更自然的分割数据操作,与将数据分成true 和false不同,可以使用任意值对数据分组。

//使用主唱对专辑分组

public Map> albumsByArtist(Stream 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 numberOfAlbums(Stream 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 countOfAlbums = new HashMap<>();

for(Map.Entry entry: albumByArtist.entrySet()>){

         Artist artist = entry.getKey();

         List albums = entry.getVaue();

         countOfAlbums.put(artist,album.size());

}

你可能感兴趣的:(第五章 高级集合类和收集器)