Java SE 8 的流库
1.迭代与流的操作
对列表中的长单词计数
1.迭代操作
long count = 0;
for(String w : words){
if.(w.length() > 12)
count++;
}
2.使用流操作实现相同功能
long count = words.stream().filter(w -> w.length() > 12),count();
使用流代替循环的好处: 流操作遵循“做什么而非怎么做原则”。
1.流版本比循环的版本更易于阅读,因为我们不必扫描整个代码去查找过滤和计数操作,方法名就可以直接告诉我们其代码意欲何为。
2.将stream()方法修改为parallelStream()方法就可以让流库以并行的方式执行过滤和计数。
流与集合的差异:
1.流并不存储其元素。(流使用的元素可能存储在底层的集合中,也可能是按照需求生成的)
2.流的操作不会修改数据源。(例如,filter()方法不会从新的流中移除元素,而是会生成一个新的流,其中不包括被过滤的掉的元素)
3.流的操作是尽可能惰性执行的。(意思是只有需要结果时,操作才会执行)
流的典型操作流程:
1.创建一个流。
2.指定将初始化流转化为其他流的中间操作,可能包含多个步骤。
3.应用终止操作,产生执行结果。
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
public class oneone {
public static void main(String[] args) throws IOException {
//读文件将文件读到集合中
String contents = new String(Files.readAllBytes(Paths.get("alice30.txt")), StandardCharsets.UTF_8);
List<String> words = Arrays.asList(contents.split("//PL+"));
long count = 0;
//循环查找集合words中单词长度大于12的单词的数量。
for(String w : words){
if (w.length() > 12){
count++;
}
}
System.out.println(count);
//单线程的流操作
count = words.stream().filter(w -> w.length() > 12).count();
System.out.println(count);
//并发执行流的操作
count = words.parallelStream().filter(w -> w.length() > 12).count();
System.out.println(count);
}
}
- Stream filter(Predicate<? super T> p):产生一个流,其中包含当前流中满足P的所有元素。
- long count():产生当前流中元素的数量。是流的一个终止操作。
- default Stream stream():产生当前集合中所有元素的顺序流
- default Stream parallelStream():产生当前集合中所有元素的并行流。
2.流的创建
使用Collection接口的stream()方法将任何集合转化为一个流。
使用静态的Stream.of()方法将数组转化为一个流。
使用Array.stream(array, from, to)方法可以从数组中位于from(包括)和to(不包括)的元素中创建一个流。
使用Stream.empty()方法创建一个不包含任何元素的流。
使用Stream.generate(Supplier<T> P)方法或Stream.iterate(UnaryOperation<T> P)方法创建无限流。
Pattern类有一个splitAsStream方法,它将按照某个正则表达式来分割一个CharSequence对象。
静态的Files.lines方法返回一个包含了文件中所有行的Stream。
Stream<String> words = Stream.of(contents.split("\\PL+"));
Stream<String> words = Stream.of("gently", "down", "the");
Stream<String> words = Array.stream(contents, 1, 5);
Stream<String> slience = Stream.empty();
Stream<String> echos = Stream.generate(()-> "Echos");
Stream<BigInteger> integers = Stream.iterate(BigInteger.ZERO, n -> n.add(BigInteger.ONE));
Stream<Stream> words = Pattern.compile("\\PL+").splitAsStream(contents);
try(Stream<String> lines = Files.lines(path))
{
Process lines;
}
import java.io.IOException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class onetwo {
public static <T> void show(String title, Stream<T> stream){
final int SIZE = 10;
List<T> firstElements = stream.limit(SIZE + 1).collect(Collectors.toList());
System.out.println(title + ": ");
for(int i = 0; i < firstElements.size(); i++){
if (i > 0) System.out.println(", ");
if (i < SIZE)
System.out.println(firstElements.get(i));
else
System.out.println("...");
}
System.out.println();
}
public static void main(String[] args) throws IOException {
Path path = Paths.get("alice30.txt");
String contents = new String(Files.readAllBytes(path), StandardCharsets.UTF_8);
//将数组转化为一个流
Stream<String> words = Stream.of(contents.split("\\PL+"));
show("words", words);
Stream<String> songs = Stream.of("gently", "down", "the", "stream");
show("song", songs);
//创建一个没有元素的流
Stream<String> empty = Stream.empty();
show("empty", empty);
//创建一个某个字符串的无限流
Stream<String> echos = Stream.generate(() ->"Echos");
show("echos", echos);
//创建一个随机数的无限流
Stream<Double> randoms = Stream.generate(Math::random);
show("randoms", randoms);
//创建一个自增的无限流
Stream<BigInteger> integerStream = Stream.iterate(BigInteger.ZERO, n -> n.add(BigInteger.ONE));
show("intergers", integerStream);
//使用Pattern将文件转为一个流
Stream<String> wordsAnotherWay = Pattern.compile("\\PL+").splitAsStream(contents);
show("wprdsAnotherWay", wordsAnotherWay);
//读文件将读到的每行转化为一个流
try(Stream<String> lines = Files.lines(path, StandardCharsets.UTF_8)){
show("lines", lines);
}
}
}
- static Stream of (T…values):产生一个元素为给定值的流。
- static Stream empty():产生一个空的流。
- static Stream generate(Suppliers):产生一个无限流,它的值是反复调用函数s而构建的。
- static Stream iterate(T seed, UnaryOperator f):产生一个无限流,它的元素包含种子、在种子上调用f产生的值、在前一个元素上调用f产生的值。
- static Stream stream(T[] array, int startInclusive, int endExclusive):产生一个流,它的元素是由数组中指定范围内的元素构成的。
- static splitAsStream(CharSequence input) :产生一个流,它的元素是输入中由该模式界定的部分。
7.static Stream lines(Path path)
8.static Stream lines(Path path, Charset cs):产生一个流,它的元素是指定文件中的行,该文件的字符集为UTF_8或者指定的字符集。
流操作的中间方法
1.filter()方法:将流转换为一个与某种条件匹配的新的流。
2.map()方法:按某种方式来转换流中的值。产生一个流,它包含将mapper应用于当前流中所有元素产生的结果。
3.flatMap()方法:产生一个流,它是通过将mapper应用于当前流中所有元素产生的结果连接到一起而获得的。
抽取子流和连接流的方法
1.limit(long maxSize)方法:产生一个流,其中包含了当前流中最初的maxSize个元素。
2.skip(long n)方法:它的元素是当前流中除了前n个元素之外的所有元素。
3.concat(Stream<?extends T> a, Stream<? extends T> b)方法:产生一个流,它的元素是a的元素后面跟着b的元素。