一、流库介绍
1.1 流提供了一种让我们可以在比集合更高的概念级别上指定计算的数据视图。通过流,我们可以说明想要完成什么任务,而不是说明如何去实现它。我们将操作的调度留给具体实现去解决。
1.2 流与集合的差别
流并不存储其元素;
流的操作不会修改其数据源;
流的操作是尽可能懒惰执行的;
二、流库使用
1. 从迭代到流的操作

2. 创建流
Path path = Paths.get("D:\\IdeaProjects\\MyConsolePrj\\src\\com\\sestream\\alice.txt");
byte[] bytes = Files.readAllBytes(path);
String contents =new String(bytes, StandardCharsets.UTF_8);
List words = Arrays.asList(contents.split("\\PL+"));
2.1 用Collection接口的stream方法将任何集合转换为一个流
Stream<String> stream= words.parallelStream();
2.2 使用静态方法Stream.of()
Stream<String> words=Stream.of(contents.split("\\PL+"));
Stream<String> songs=Stream.of("gently","down","song");
2.3 使用静态Stream.empty()产生空流
Stream<String> slience=Stream.empty();
2.4 使用静态方法generate/iterate方法创建无限流
Stream<String> echos=Stream.generate(()->"Echo");
Stream<Double> randoms=Steam.iterate(BigInteger.ONE,n->n.add(BigInteger.ONE));
2.5 使用Pattern类产生流库
Stream<String> words=Pattern.compile("\\PL+").splitAsStream(contents);
2.6 使用静态方法Files.lines产生流库
try(Stream<String> lines=Files.lines(path,StandardCharsets.UTF-8 )){。。。}
3. filter \map\flatMap方法

4. 抽取子流和连接流
产生一个包含100个随机数的流:Stream<Double> randoms=Stream.generate(Math::random).limit(100);
丢弃前n个元素:Stream<String> words=Stream.of(contents.split("\\PL+")).skip(1);
连接两个流:Stream<String> combined=Stream.concat(letter("Hello"),letter("World"));

5. 其他的流转换
剔除重复元素:Stream<String> unique=Stream.of("merril","tom","merri").distinct();
排序使最长的字符串排在前面:Stream<String> longest=words.stream().sorted(Comparator.comparing(String::length).reversed());
peek方法每次获取元素前调用函数(未改变原元素值):
Object[] powers=Stream.iterate(1.0,p->p*2).peek(e->System.out.println("Fetching"+e)).limit(20).toArray();
6. 简单约简
约简是一种终结操作,他们会将流约简未可以在程序中使用的非流值
// max min findFirst findAny() anyMatch........等等
long count = words.stream().filter(w -> w.length() >12).count();
Optional<String> largest=words.stream().max(String::compareToIgnoreCase);
Optional<String> first= words.parallelStream().filter(s -> s.startsWith("a")).findFirst();
//reduce 约简 求和
List<Integer> values=...;
Optional<Integer> sum=values.stream().reduce((x,y)->x+y);
sum=values.stream().reduce(Integer::sum);
7. Optional类型
Optional<T>对象是一种对象包装器,要么包含了类型T的对象,要么没有包装任何对象。
//没有值时默认空字符串 String result=optionalValie.orElse("");
//设置默认值 String result=optionalValue.orElsGet(()->Locale.getDefault.getDisplayName());
//无值时抛出异常 String result=optionalValue.orElseThrow(IllegalstateException:;new);
//当值存在时,将值加入某集合(该函数不会返回任何值)
optionalValue.ifPresent(w->tmpList.add(w));
//将值加入某集合(返回是否加入成功)
Optional<boolean> added=optionalValue.map(tmpList::add);
8. 创建Optional值
产生一个空Optional:Optional.empty();
产生一个Optional:Optional.of(tmpValue);/ Optional.ofNullable(tmpValue);
//flatMap的调用链接起来,从而构建由这些步骤构成的管道,只有所有步骤都成功时,该管道才会成功
Optional<Double> result=Optional.of(-4).flatMap(OptionalTest::reverse).flatMap(OptionalTest::squareRoot);
public static Optional<Double> inverse(Double x)
{ return x==0?Optional.empty():Optional.of(1/x); }
public static Optional<Double> squareRoot(Double x)
{ return x<0? Optional.empty():Optional.of(Math.sqrt(x)); }
9. 收集结果
9.1 传统方式:
//迭代器
Iterator iterator = stream.iterator();
if (iterator.hasNext()) {
System.out.println(iterator.next());
}
//forEach
stream.forEach(w -> System.out.println(w));
9.2 将结果收集到数据结构中


9.3 群组与分区
Stream localeStream = Stream.of(Locale.getAvailableLocales());
//快速分组
Map> countryToLocales = localeStream.collect(Collectors.groupingBy(Locale::getCountry));
// 分类函数 返回是否使用英语的国家
Map<Boolean, List<Locale>> englisthAndOtherLocales = localeStream.collect(Collectors.partitioningBy(l -> l.getLanguage().equals("en")));
10. 基本类型流
double、float、long、short、char、byte、boolean
11. 并行流
只有在对已经位于内存中的数据执行大量计算操作时,才应该使用并行流
1. 获取并行流
//使用Collection.parallelStream(),可以从任何集合中获取一个并行流
Stream<String> parallelWords=words.parallelStream();
//使用parallel方法可以从任意顺序流转换为并行流
Stream<String> parallelWords=Stream.of(wordArray).parallel();
2. 对字符串流中所有短单词计数

3. 排序问题
默认情况下,从有序集合、范围、生成器和迭代产生的流,或通过调用Stream.sorted产生的流,都是有序的;
排序并不排斥高效的并行处理;
当放弃排序时,有些操作可以被更有效的并行化。通过在流上调用unordered方法,就可以明确标识我们对排序不感兴趣。
//可以通过放弃排序来提高limit方法的速度
Steam<String> sample=words.parallelStream().unordered().limit(n);
//合并映射表的代价很高昂,正式这个原元,Collectors.groupByConcurrent方法使用了共享的并发映射表
Map<Integer,List<String>> result=words.parallelSteam().collect(Collectors.groupingByConcurrent(String::length));
Map<Integer,Long> wordCounts=words.parallelSteam().collect(Collectors.groupingByConcurrent(String::length,countint()));
网友评论