1.类说明
- Album:专辑类,包含了专辑名称,专辑上所有曲目的列表,参与创作本专辑的艺术家列表
- Artist:乐队类,包含了乐队名字,乐队成员,乐队国籍
- Track:专辑中的一支曲目,包含了曲目名称,曲目时长
- Albums:提供了4个专辑,以及一些功能方法,主要是为了在测试时,直接使用,避免测试类中创建太多非测试逻辑的代码。
2.code
Album类
package java8;
import java.util.ArrayList;
import java.util.List;
/**
* @Author: cxh
* @CreateTime: 17/12/14 20:38
* @ProjectName: JavaBaseTest
* <专辑></>
*/
public class Album {
String name;//专辑名称
List<Track> tracks;//专辑上所有曲目的列表
List<Artist> musicians;//参与创作本专辑的艺术家列表
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Track> getTracks() {
return tracks;
}
public void setTracks(ArrayList<Track> tracks) {
this.tracks = tracks;
}
public List<Artist> getMusicians() {
return musicians;
}
public void setMusicians(ArrayList<Artist> musicians) {
this.musicians = musicians;
}
Album(String name,List<Track> tracks,List<Artist> musicians){
this.name=name;
this.tracks=tracks;
this.musicians=musicians;
}
//获取主唱
public String getMainMusician(){
return musicians.get(0).getMembers().get(0);
}
@Override
public String toString() {
return "Album{" +
"name='" + name + '\'' +
", tracks=" + tracks +
", musicians=" + musicians +
'}';
}
}
Artist类
package java8;
import java.util.ArrayList;
import java.util.List;
/**
* @Author: cxh
* @CreateTime: 17/12/14 20:37
* @ProjectName: JavaBaseTest
* <创作音乐的个人或者团队></>
*/
public class Artist {
String name;//艺术家的名字
List<String> members;//乐队成员
String original;//乐队来自哪里
public String getOriginal() {
return original;
}
public void setOriginal(String original) {
this.original = original;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getMembers() {
return members;
}
public void setMembers(ArrayList<String> members) {
this.members = members;
}
Artist(String name,List<String> members,String original){
this.name=name;
this.members=members;
this.original=original;
}
//
//toString
@Override
public String toString() {
return "Artist{" +
"name='" + name + '\'' +
", members=" + members +
", original='" + original + '\'' +
'}';
}
}
Track类
package java8;
/**
* @Author: cxh
* @CreateTime: 17/12/14 20:38
* @ProjectName: JavaBaseTest
* <专辑中的一支曲目></>
*/
public class Track {
String name;//曲目名称
int length;//曲目时常
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
Track(String name, int len){
this.name=name;
this.length=len;
}
//toString
@Override
public String toString() {
return "Track{" +
"name='" + name + '\'' +
", length=" + length +
'}';
}
}
Albums类
package java8;
import java.util.ArrayList;
import java.util.List;
/**
* @Author: cxh
* @CreateTime: 18/3/17 09:11
* @ProjectName: JavaBaseTest
*/
public class Albums {
private static List<Album> albums;
private static void init(){
albums=new ArrayList<>();
//第一张专辑
//beyongd乐队,成员:黄家驹、黄贯中、黄家强、叶世荣 && 歌曲:真的爱你,喜欢你,海阔天空,大地
List<String> members1=new ArrayList<>();
members1.add("黄家驹");members1.add("黄贯中");members1.add("黄家强");members1.add("叶世荣");
List<Artist> artists1=new ArrayList<>();
artists1.add(new Artist("beyongd乐队",members1,"中国"));
List<Track> tracks1=new ArrayList<>();
tracks1.add(new Track("真的爱你",3));
tracks1.add(new Track("喜欢你",4));
tracks1.add(new Track("海阔天空",5));
tracks1.add(new Track("大地",3));
albums.add(new Album("beyond乐队专辑",tracks1,artists1));
//第二张专辑
//瘦人乐队,成员:戴秦,周坤 && 歌曲:《瘦人I》《瘦人I》《第七天》EP《一路向北》
List<String> members2=new ArrayList<>();
members2.add("戴秦");members2.add("周坤");
List<Artist> artists2=new ArrayList<>();
artists2.add(new Artist("瘦人乐队",members2,"中国"));
List<Track> tracks2=new ArrayList<>();
tracks2.add(new Track("瘦人I",3));
tracks2.add(new Track("瘦人II",3));
tracks2.add(new Track("第七天",3));
tracks2.add(new Track("一路向北",3));
albums.add(new Album("瘦人乐队专辑",tracks2,artists2));
//第三张专辑
//五月天乐队,成员:温尚翊、阿信、石头、贝斯玛莎,冠佑 && 歌曲:别惹我,知足,倔强,温柔\
List<String> members3=new ArrayList<>();
members3.add("温尚翊");members3.add("阿信");members3.add("石头");members3.add("贝斯玛莎");members3.add("冠佑");
List<Artist> artists3=new ArrayList<>();
artists3.add(new Artist("五月天乐队",members3,"中国"));
List<Track> tracks3=new ArrayList<>();
tracks3.add(new Track("别惹我",3));tracks3.add(new Track("知足",3));
tracks3.add(new Track("倔强",3));tracks3.add(new Track("温柔",3));
albums.add(new Album("五月天乐队专辑",tracks3,artists3));
//第四章专辑
//天堂乐队:雷刚,羊力,贺成功,仲夏,孙永栋 && 歌曲:少年,过年喽,战斗
List<String> members4=new ArrayList<>();
members4.add("雷刚"); members4.add("羊力"); members4.add("贺成功");
members4.add("仲夏"); members4.add("孙永栋");
List<Artist> artists4=new ArrayList<>();
artists4.add(new Artist("天堂乐队",members4,"中国"));
List<Track> tracks4=new ArrayList<>();
tracks4.add(new Track("少年",3));tracks4.add(new Track("过年喽",3));
tracks4.add(new Track("战斗",3));
albums.add(new Album("天堂乐队专辑",tracks4,artists4));
}
public static List<Album> getAlbums(){
init();
return albums;
}
}
测试类
package java8;
import java.util.*;
import java.util.function.*;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* @Author: cxh
* @CreateTime: 17/12/14 20:47
* @ProjectName: JavaBaseTest
* <测试类></>
*/
public class Test{
public static void main(String[] args) {
List<Album> albums=Albums.getAlbums();
//方法引用::,获取专辑名字
albums.stream().map(Album::getName).forEach(s-> System.out.println(s));
//转换为其它集合,Collectors收集器的使用
Set<Album> setAlbums=albums.stream().collect(Collectors.toSet());
Set<Album> setAlbums2=albums.stream().collect(Collectors.toCollection(HashSet::new));//定制集合类型
//转换为值
//maxBy:找出成员最多的乐队
Function<Artist,Integer> maxByFun=art->art.getMembers().size();
Set<Artist> artists=albums.stream().map(album -> album.getMusicians().get(0)).collect(Collectors.toSet());
Optional<Artist> maxMem=artists.stream().collect(Collectors.maxBy(Comparator.comparing(maxByFun)));
System.out.println(maxMem.get());
//找出一组专辑上曲目的平均数目
double avg=albums.stream().collect(Collectors.averagingInt(alb->alb.getTracks().size()));
System.out.println("专辑曲目平均值avg="+avg);
//数据分块,按照专辑上曲目个数进行分类
Map<Integer,List<Album>> albumBySize=albums.stream().
collect(Collectors.groupingBy(album -> album.getTracks().size()));
albumBySize.forEach((k,v)->{
System.out.println("曲目个数为"+k+"的专辑为:"+v);
});
//字符串拼接joining
String names=albums.stream().map(albs->albs.getName()).collect(Collectors.joining(",","[","]"));
System.out.println("拼接字符串为:"+names);
//downstream下游收集器:获取每个主唱的专辑名
Map<String,List<String>> partByArt=albums.stream().collect(Collectors.groupingBy(
Album::getMainMusician,Collectors.mapping(Album::getName,Collectors.toList())));
partByArt.forEach((k,v)->{
System.out.println("主唱="+k+" and 专辑名字="+v);
});
//使用reduce和StringJoiner类格式化艺术家姓名
StringJoiner joiner=albums.get(0).getMusicians().get(0).getMembers().stream().
reduce(new StringJoiner(",","[","]"),StringJoiner::add,StringJoiner::merge);
System.out.println(joiner);
//joining收集器,非常方便,这就显得上面的方法有些笨拙
List<String> strs=albums.get(0).getMusicians().get(0).getMembers();
System.out.println(strs.stream().collect(Collectors.joining(",","[","]")));
//测试自定义收集器
List<String> nas=albums.get(0).getMusicians().get(0).getMembers();
System.out.println(nas.stream().collect(new StringCollector(",","<<",">>")));
//并行化计算专辑曲目的长度(并行化流操作)
int sumLen=albums.parallelStream().flatMap(as->as.getTracks().stream()).
mapToInt(Track::getLength).sum();
System.out.println("4张专辑中所有歌曲的总时长(单位:分钟):"+sumLen);
//求投掷骰子每个点出现的次数和概率的映射
int N=1000;//模拟次数
double fracton=1.0/N;
IntFunction<Integer> function=(i)->{
Random random=new Random();
int min=1,max=6;
//nextInt返回[0,max]的数
int res=random.nextInt(max)%(max-min+1)+1;//通用公式
return res;
};
Map<Integer,Double> map= IntStream.range(0,N).parallel().mapToObj(function).
collect(Collectors.groupingBy(i->i,Collectors.summingDouble(n->fracton)));
map.forEach((k,v)->{
System.out.println("k="+k+" and value="+v);
});
/*并行化数组操作*/
//1.parallePrefix,
double[] para1=new double[20];
Arrays.fill(para1,1);
Arrays.parallelPrefix(para1,Double::sum);
System.out.println("para1[19]理论值为20.0,实际值为:"+para1[19]);
//2.paralleSetAll
double[] para2=new double[20];
Arrays.setAll(para2,i->i);
System.out.println("para2[19]理论值为19.0,实际值为:"+para2[19]);
//3.paralleSort
double[] para3=new double[20];
Arrays.parallelSetAll(para3,i->20-i);
System.out.println("排序前:para3[19]="+para3[19]+",para3[0]="+para3[0]);
Arrays.parallelSort(para3);
System.out.println("排序后:para3[19]="+para3[19]+",para3[0]="+para3[0]);
//计算滑动窗口的平均值,设定窗口大小n=4
int n=4,len=20;
double[] windowns=new double[len];
Arrays.parallelSetAll(windowns,i->i);
Arrays.parallelPrefix(windowns,Double::sum);
int start=n-1;
double[] result=IntStream.range(start,len)
.mapToDouble(i->{
double prefix=i==start?0:windowns[i-n];
return (windowns[i]-prefix)/n;
})
.toArray();
Spliterator<Double> spl=Arrays.spliterator(result);
spl.forEachRemaining(d-> System.out.print(d+","));
System.out.println();
//使用领域方法重构类
//总时长统计
ToIntFunction<Album> f1=a->a.getTracks().stream().mapToInt(Track::getLength).sum();
int sunTime=countFeature(f1,albums);
System.out.println("4张专辑总时长:"+sunTime);
//歌曲数目统计
ToIntFunction<Album> f2=a->a.getTracks().size();
int sumMu=countFeature(f2,albums);
System.out.println("歌曲总数:"+sumMu);
//使用peek方法记录中间值,乐队名
Set<String> mainMus=albums.stream().flatMap(album -> album.getMusicians().stream())
.map(artist -> artist.getName())
.peek(s1 -> System.out.println("我是peek()记录的中间值:"+s1))
.collect(Collectors.toSet());
mainMus.forEach(s -> System.out.println("乐队名字:"+s));
//利用并行流计算指定范围内的质数个数
IntPredicate isPrime=i->{return IntStream.range(2,i)
.parallel().allMatch(x->i%x!=0);};
long countRange=IntStream.range(1,100).parallel().filter(isPrime).count();
System.out.println("[1,100]范围内质数的个数:"+countRange);
//
}
//领域方法
private static int countFeature(ToIntFunction<Album> func,List<Album> albums){
return albums.stream().mapToInt(func).sum();
}
}
//定制收集器,用于连接字符串,但是jdk8中的joining收集器已经很好了,这里只是测试自定义收集器的过程
class StringCollector implements Collector<String,StringJoiner,String>{
private String preFix;
private String delimiter;
private String endFix;
StringCollector(String deli,String pre, String end){
this.preFix=pre;;
this.delimiter=deli;
this.endFix=end;
}
//生产者
@Override
public Supplier<StringJoiner> supplier() {
return ()->new StringJoiner(delimiter,preFix,endFix);
}
//将当前元素添加到收集器中
@Override
public BiConsumer<StringJoiner, String> accumulator() {
return StringJoiner::add;
}
//收集器合并
@Override
public BinaryOperator<StringJoiner> combiner() {
return StringJoiner::merge;
}
//返回收集操作的最终结果
@Override
public Function<StringJoiner, String> finisher() {
return StringJoiner::toString;
}
@Override
public Set<Characteristics> characteristics() {
Set<Characteristics> set=new HashSet<>();
set.add(Characteristics.CONCURRENT);
set.add(Characteristics.UNORDERED);
return set;
}
}
参考书籍:《java8函数式编程》