1.方法引用
Lambda 表达式有一个常见的用法: Lambda 表达式经常调用参数。 比如想得到艺术家的姓名, Lambda 的表达式如下:
artist -> artist.getName()
这种用法如此普遍, 因此 Java 8 为其提供了一个简写语法, 叫作方法引用, 帮助程序员重用已有方法。 用方法引用重写上面的 Lambda 表达式, 代码如下:
Artist::getName
标准语法为 Classname::methodName。
2.使用收集器
package com.mmmm.test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.StringJoiner;
import java.util.TreeSet;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.mmmm.model.Album;
import com.mmmm.model.Artist;
import com.mmmm.model.Track;
public class Test_03 {
public static void main(String[] args) {
List<String> list_01=Stream.of("1", "2", "3")
.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
System.out.println(list_01);
String list_02=Stream.of("1", "2", "3")
.collect(Collectors.collectingAndThen(Collectors.toList(), list->list.toString()));
System.out.println(list_02);
List<String> list_03=Stream.of("1", "2", "3")
.collect(Collectors.toList());
System.out.println(list_03);
Set<String> list_04=Stream.of("1", "2", "3")
.collect(Collectors.toSet());
System.out.println(list_04);
TreeSet<String> list_05=Stream.of("5", "2", "3")
.collect(Collectors.toCollection(TreeSet::new));
System.out.println(list_05);
//1.找出成员最多的乐队
List<Artist> musicians=new ArrayList<Artist>();
musicians.add(new Artist("JiaKeChong",Arrays.asList("zhangsan","lisi","wangwu") , "Americ"));
musicians.add(new Artist("TFBOYS",Arrays.asList("wangyuan","wang","yiyangqianxi") , "China"));
musicians.add(new Artist("xiha",Arrays.asList("lili") , "Italy"));
musicians.add(new Artist("yangmi",Arrays.asList("lilian") , "Italy"));
System.out.println("成员最多的乐队:方法一"+biggestGroup_01(musicians.stream()).get());
System.out.println("成员最多的乐队:方法二"+biggestGroup_02(musicians.stream()).get());
//2.找出一组专辑上曲目的平均数
List<Album> albumList = new ArrayList<>();
List<Track> trackList_1 = new ArrayList<>();
trackList_1.add(new Track("song_01"));
List<Track> trackList_2 = new ArrayList<>();
trackList_2.addAll(trackList_1);
trackList_2.add(new Track("song_02"));
trackList_2.add(new Track("song_03"));
List<Track> trackList_3 = new ArrayList<>();
trackList_3.addAll(trackList_2);
trackList_3.add(new Track("song_04"));
trackList_3.add(new Track("song_05"));
trackList_3.add(new Track("song_06"));
trackList_3.add(new Track("song_07"));
albumList.add(new Album("xingxing", trackList_1, musicians));
albumList.add(new Album("xingxing", trackList_2, musicians));
albumList.add(new Album("xingxing", trackList_3, musicians));
System.out.println("专辑上曲目的平均数:"+averageNumberOfTracks(albumList));
System.out.println("专辑上曲目的总数:"+sumNumberOfTracks(albumList));
//3.数据分块
System.out.println("艺术家里面是solo的是:"+getArtistIsSoloOrNot(musicians).get(true));
System.out.println("艺术家里面不是solo的是:"+getArtistIsSoloOrNot(musicians).get(false));
//4.字符串
System.out.println("艺术家的姓名:"+getName(musicians));
StringJoiner combined =
musicians.stream()
.map(Artist::getName)
.reduce(new StringJoiner(", ", "[", "]"),
StringJoiner::add,
StringJoiner::merge);
String result = combined.toString();
System.out.println(result);
}
/**
* 找出成员最多的乐队方法1
* @param artists
* @return
*/
public static Optional<Artist> biggestGroup_01(Stream<Artist> artists) {
Function<Artist,Long> getCount = artist ->artist.getMembers()==null?0:artist.getMembers().stream().count();
return artists.collect(Collectors.maxBy(Comparator.comparing(getCount)));
}
/**
* 找出成员最多的乐队方法2
* @param artists
* @return
*/
public static Optional<Artist> biggestGroup_02(Stream<Artist> artists) {
return artists.collect(Collectors.maxBy(Comparator.comparing(artist ->artist.getMembers()==null?0:artist.getMembers().stream().count())));
}
/**
* 找出一组专辑上曲目的平均数
* @param albums
* @return
*/
public static double averageNumberOfTracks(List<Album> albums) {
return albums.stream()
.collect(Collectors.averagingInt(album -> album.getTracks().size()));
}
/**
* 找出一组专辑上曲目的总数
* @param albums
* @return
*/
public static double sumNumberOfTracks(List<Album> albums) {
return albums.stream()
.collect(Collectors.summingDouble(album -> album.getTracks().size()));
}
/**
* 数据分块
* 艺术家中是solo的和不是solo的分块
*
*/
public static Map<Boolean, List<Artist>> getArtistIsSoloOrNot(List<Artist> artists){
return artists.stream().collect(Collectors.partitioningBy(artist->artist.getMembers().size()==1));
}
/**
* 编写一个函数,接受艺术家列表作为参数,返回一个字符串列表,其中包含艺术家的姓名;
*
* @param musicians
* @return
*/
public static String getName(List<Artist> musicians) {
String nameAndOrigin = musicians.stream()
// .map(artist -> "name:" + artist.getName() + ",origin:" + artist.getOrigin() + ";")
.map(Artist::getName)
.collect(Collectors
.joining(",name:", "[name:", "]"));
return nameAndOrigin;
}
/**
* 组合收集器
* 使用收集器求每个艺术家的专辑名
* @param albums
* @return
*/
public Map<Artist, List<String>> nameOfAlbums(Stream<Album> albums) {
return albums.collect(Collectors.groupingBy(Album::getMainMusician,
Collectors.mapping(Album::getName, Collectors.toList())));
}
/**
* 组合收集器
* 使用收集器计算每个艺术家的专辑数
* @param albums
* @return
*/
public Map<Artist, Long> numberOfAlbums(Stream<Album> albums) {
return albums.collect(Collectors.groupingBy(album -> album.getMainMusician(),
Collectors.counting()));
}
}
3.练习题
/*1. 方法引用
回顾第 3 章中的例子, 使用方法引用改写以下方法:
a. 转换大写的 map 方法;
b. 使用 reduce 实现 count 方法;
c. 使用 flatMap 连接列表。*/
//a. 转换大写的 map 方法;
System.out.println(Stream.of("a","b","c").map(String::toUpperCase).collect(Collectors.toList()));
System.out.println(Stream.of("a","b","c").map(str->str.toUpperCase()).collect(Collectors.toList()));
//b. 使用 reduce 实现 count 方法;
System.out.println(Stream.of(1,2,3).reduce(0,(acc,element)->acc+element));
//c. 使用 flatMap 连接列表
List<Integer> together = Stream.of(Arrays.asList(1, 2), Arrays.asList(3, 4))
.flatMap(Collection::stream)
.collect(Collectors.toList());
System.out.println(together);
2. 收集器
a. 找出名字最长的艺术家, 分别使用收集器和第 3 章介绍过的 reduce 高阶函数实现。68 | 第 5 章
然后对比二者的异同: 哪一种方式写起来更简单, 哪一种方式读起来更简单? 以下面
的参数为例, 该方法的正确返回值为 "Stuart Sutcliffe":
Stream<String> names = Stream.of("John Lennon", "Paul McCartney",
"George Harrison", "Ringo Starr", "Pete Best", "Stuart Sutcliffe");
//1.找出名字最长的艺术家
Stream<String> names = Stream.of("John Lennon", "Paul McCartney",
"George Harrison", "Ringo Starr", "Pete Best", "Stuart Sutcliffe");
System.out.println("名字最长的艺术家:"+names.collect(Collectors.maxBy(Comparator.comparing(name->name.length()))).get());
b. 假设一个元素为单词的流, 计算每个单词出现的次数。 假设输入如下, 则返回值为一
个形如 [John → 3, Paul → 2, George → 1] 的 Map:
Stream<String> names = Stream.of("John", "Paul", "George", "John",
"Paul", "John");
//2.假设一个元素为单词的流, 计算每个单词出现的次数。 假设输入如下, 则返回值为一个形如 [John → 3, Paul → 2, George → 1] 的 Map
Stream<String> names2 = Stream.of("John", "Paul", "George", "John",
"Paul", "John");
Map<String,Long> map=names2.collect(Collectors.groupingBy(name->name,Collectors.counting()));
System.out.println(map);
Stream<String> names3 = Stream.of("John", "Paul", "George", "John",
"Paul", "John");
Map<Object, List<String>> map2=names3.collect(Collectors.groupingBy(name->name));
System.out.println(map2);