Files.lines
)filter(Predicate)
count()
可以获得流中数据的长度, 而foreach(Consumer)
可以对流中所有的数据依次操作常用的Stream接口继承关系如下图:
如上图, Stream
接口继承于BaseStream
; 主要可以分为针对基本类型的LongStream
/IntStream
/DoubleStream
和针对Object
实现的通用的Stream
接口; 这样既保证了面向对象的操作, 也保证了对基本类型的兼容
filter
filter
用于根据predicate
中定义的方法来过滤集合中的元素, 如下面的例子integer -> integer > 3
就过滤掉了小于或等于3
的元素
public void filter() {
Arrays.asList(1, 2, 3, 4, 5, 6, 7)
.stream()
.filter(integer -> integer > 3)
.forEach(System.out::println);
}
map
map的功能是对Stream中的元素进行转换, 转换规则为传入的mapper
函数; 转换过程不会改变元素的数量, 只会改变元素的类型和值; 下面的例子中, 将所有字符都包裹上了尖括号
public void map() {
Arrays.stream("It's a wonderful day for me".split(" "))
.map(s -> "<" + s + ">")
.forEach(System.out::println);
}
flatMap
flatMap
类似于map
; 但是他会将mapper
返回的的流"摊平"(flatten); 此过程不同于map
, 它会改变元素的数量, 同时也会改变元素的类型和值; 下面的例子会将原列表中所有的数字列表摊平, 并形成一个新的流, 即一个包含1-7所有数字的流
public void flatMap() {
Arrays.asList(Collections.singleton(1), Arrays.asList(2, 3, 4), Set.of(5,6,7))
.stream()
.flatMap(Collection::stream)
.forEach(System.out::println);
}
forEach
forEach
是对容器中的每个元素执行传入的Consumer
的操作; 如下面的例子, 传入的是System.out::println
, 因此会打印每个元素
public void foreach() {
Arrays.asList(1, 2, 3, 4, 5, 6, 7)
.stream()
.forEach(System.out::println);
}
sorted
sorted
函数有两个, 一个是按照自然顺序排序, 另一个是使用自定义比较器排序, 对应的是Comparator.naturalOrder()
其底层会调用Comparable.compareTo
; 下面的例子对字符串的长度记性升序排序
public void sorted() {
Arrays.stream("It's a wonderful day for me".split(" "))
.sorted((s1, s2) -> s1.length() - s2.length())
.forEach(System.out::println);
}
reduce
reduce
操作可以从一组元素中规约生成一个值, 它可以实现多种操作, 在java流中max
, min
, sum
, count
的本质都是规约操作; 下面是规约操作的定义, 它通过一个初始值identity
进行累加, 最后生成一个值, 在并发并发情况下, 还可能会需要对多个累加的值进行合并
<U> U reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator<U> combiner);
max
下面是对reduce
的一个最基本的使用, 找到长度最大的字符串的值; 它从第一个元素开始累计, 每次对比两个元素并取较大的元素; 如此进行累加, 最后得到的便是最大的元素
System.out.println(Stream.of("I", "love", "you", "too")
.reduce((s1, s2) -> s1.length() >= s2.length() ? s1 : s2)
.orElse(null));
System.out.println(Stream.of("I", "love", "you", "too")
.max((s1, s2) -> s1.length() - s2.length())
.orElse(null));
sum
max
无需指定幺元identity
和combiner
因为它是从第一个元素开始累加的; 其会从第一个元素开始累积, 并且会调用acuumulator
进行combine
; 而sum
方法需要自己指定初始值为0
, 并指定combiner
的逻辑为两个分段的相加, 如下面的例子计算流中的字符数
public void totalLength() {
System.out.println(Stream.of("I", "love", "you", "too")
.reduce(0
, (total, s) -> total + s.length()
, (a, b) -> a + b));
}