以下部分内容来自菜鸟教程、文档Api、马士兵教育课堂
Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
什么是 Stream?
Stream(流)是一个来自数据源的元素队列并支持聚合操作
- 元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
- 数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
- 聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。
和以前的Collection操作不同, Stream操作还有两个基础的特征:
- Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
- 内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。
Stream特性
- 不是数据结构,没有内部存储
- 不支持索引访问
- 延迟计算
- 支持并行
- 很容易生成数组或者集合(List,Set)
- 支持过滤,查找,转换,汇算,聚合等操作。
Stream运行机制
- stream分为源source 、中间操作、终止操作。
- 流的源可以以是一个数组、一个集合、一个生成器方法、一个I/O通道等等。
- 一个流可以零个和或者多个中间操作、每一个中间操作操作都会返回一个新的流、供下一个操作使用、它的源才开始执行遍历操作。
- Stream只有遇到终止操作,它的源才开始执行遍历操作。
Stream创建
- 数组
- 集合
- Stream.generate方法来创建
- Stream.iterate方法来创建
- 其他API创建
Stream常用API
- 终止操作
- 循环forEach
- 计算min,max,count,average
- 匹配anyMatch、allMatch、noneMatch、findFirst、findAny
- 汇聚reduce
收集器toArray、collect
-
-
Modifier and Type
Method and Description boolean
allMatch(Predicate<? super T> predicate)
返回此流的所有元素是否与提供的谓词匹配。
static <T> Stream.Builder<T>
builder()
返回一个
Stream
的构建器。<R,A> R
collect(Collector<? super T,A,R> collector)
使用 Collector对此流的元素执行 mutable reduction
Collector
。<R> R
collect(Supplier<R> supplier, BiConsumer<R,? super T> accumulator, BiConsumer<R,R> combiner)
对此流的元素执行 mutable reduction操作。
static <T> Stream<T>
concat(Stream<? extends T> a, Stream<? extends T> b)
创建一个懒惰连接的流,其元素是第一个流的所有元素,后跟第二个流的所有元素。
long
count()
返回此流中的元素数。
Stream<T>
distinct()
返回由该流的不同元素(根据
Object.equals(Object)
)组成的流。static <T> Stream<T>
empty()
返回一个空的顺序
Stream
。Stream<T>
filter(Predicate<? super T> predicate)
返回由与此给定谓词匹配的此流的元素组成的流。
Optional<T>
findAny()
返回描述流的一些元素的
Optional
如果流为空,则返回一个空的Optional
。Optional<T>
findFirst()
返回描述此流的第一个元素的
Optional
如果流为空,则返回一个空的Optional
。<R> Stream<R>
flatMap(Function<? super T,? extends Stream<? extends R>> mapper)
返回由通过将提供的映射函数应用于每个元素而产生的映射流的内容来替换该流的每个元素的结果的流。
DoubleStream
flatMapToDouble(Function<? super T,? extends DoubleStream> mapper)
返回一个
DoubleStream
,其中包含将该流的每个元素替换为通过将提供的映射函数应用于每个元素而产生的映射流的内容的结果。IntStream
flatMapToInt(Function<? super T,? extends IntStream> mapper)
返回一个
IntStream
,其中包含将该流的每个元素替换为通过将提供的映射函数应用于每个元素而产生的映射流的内容的结果。LongStream
flatMapToLong(Function<? super T,? extends LongStream> mapper)
返回一个
LongStream
,其中包含将该流的每个元素替换为通过将提供的映射函数应用于每个元素而产生的映射流的内容的结果。void
forEach(Consumer<? super T> action)
对此流的每个元素执行操作。
void
forEachOrdered(Consumer<? super T> action)
如果流具有定义的遇到顺序,则以流的遇到顺序对该流的每个元素执行操作。
static <T> Stream<T>
generate(Supplier<T> s)
返回无限顺序无序流,其中每个元素由提供的
Supplier
。static <T> Stream<T>
iterate(T seed, UnaryOperator<T> f)
返回有序无限连续
Stream
由函数的迭代应用产生f
至初始元素seed
,产生Stream
包括seed
,f(seed)
,f(f(seed))
,等Stream<T>
limit(long maxSize)
返回由此流的元素组成的流,截短长度不能超过
maxSize
。<R> Stream<R>
map(Function<? super T,? extends R> mapper)
返回由给定函数应用于此流的元素的结果组成的流。
DoubleStream
mapToDouble(ToDoubleFunction<? super T> mapper)
返回一个
DoubleStream
,其中包含将给定函数应用于此流的元素的结果。IntStream
mapToInt(ToIntFunction<? super T> mapper)
返回一个
IntStream
,其中包含将给定函数应用于此流的元素的结果。LongStream
mapToLong(ToLongFunction<? super T> mapper)
返回一个
LongStream
,其中包含将给定函数应用于此流的元素的结果。Optional<T>
max(Comparator<? super T> comparator)
根据提供的
Comparator
返回此流的最大元素。Optional<T>
min(Comparator<? super T> comparator)
根据提供的
Comparator
返回此流的最小元素。boolean
noneMatch(Predicate<? super T> predicate)
返回此流的元素是否与提供的谓词匹配。
static <T> Stream<T>
of(T... values)
返回其元素是指定值的顺序排序流。
Stream<T>
peek(Consumer<? super T> action)
返回由该流的元素组成的流,另外在从生成的流中消耗元素时对每个元素执行提供的操作。
Optional<T>
reduce(BinaryOperator<T> accumulator)
使用 associative累积函数对此流的元素执行 reduction ,并返回描述减小值的
Optional
(如果有)。T
reduce(T identity, BinaryOperator<T> accumulator)
使用提供的身份值和 associative累积功能对此流的元素执行 reduction ,并返回减小的值。
Stream<T>
skip(long n)
在丢弃流的第一个
n
元素后,返回由该流的n
元素组成的流。Stream<T>
sorted()
返回由此流的元素组成的流,根据自然顺序排序。
Object[]
toArray()
返回一个包含此流的元素的数组。
-
package com.streams;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Stream API 方法实践
*/
public class StreamDemo {
public static void main(String[] args) {
System.out.println("输出集合的值:");
Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8).stream().filter((x) -> x % 2 == 0).forEach(System.out::println);
System.out.println("求偶数的和:");
System.out.println(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8).stream().filter((x) -> x % 2 == 0).mapToInt((x) -> {
return x;
}).sum());
System.out.println(" Stream.builder():");
List<Integer> asList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
Stream.Builder<Object> objectBuilder = Stream.builder().add(asList);
Stream<Object> build = objectBuilder.build();
build.forEach(System.out::println);
System.out.println("求集合最大值:");
Optional<Integer> optional = asList.stream().max((a, b) -> a - b);
System.out.println(optional.get());
System.out.println("求集合的最小值:");
System.out.println(asList.stream().min((a, b) -> a - b).get());
System.out.println(asList.stream().filter(x -> x % 2 == 0).findAny().get());
System.out.println(asList.stream().findFirst().get());
Stream<Integer> stream = asList.stream().filter(i -> {
System.out.println("云心代码");
return i % 2 == 0;
});
System.out.println(stream.findFirst().get());
System.out.println("获取最小和最大值,不使用min和max方法:");
System.out.println(asList.stream().sorted().findFirst().get());
System.out.println(asList.stream().sorted().findAny().get());
System.out.println(asList.stream().sorted((a, b) -> b - a).findFirst().get());
Arrays.asList("java", "c#", "scala", "python").stream().sorted().forEach(System.out::println);
Arrays.asList("java", "c#", "scala", "python").stream().sorted((a, b) -> a.length() - b.length()).forEach(System.out::println);
System.out.println("想将集合的元素进行过滤同时返回一个集合对象:");
List<Integer> collect = asList.stream().filter(x -> x % 2 == 0).collect(Collectors.toList());
collect.forEach(System.out::println);
System.out.println("去重操作:");
System.out.println("使用distinct方法去重:");
List<Integer> integers = Arrays.asList(1, 2, 3, 3, 4, 5, 6, 7, 7);
integers.stream().distinct().forEach(System.out::println);
System.out.println("使用Set集合去重:");
Set<Integer> set = integers.stream().collect(Collectors.toSet());
set.forEach(System.out::println);
System.out.println("//打印20-30这样的集合元素:");
Stream<Integer> limit = Stream.iterate(1, x -> x + 1).limit(50).skip(20).limit(10);
limit.forEach(System.out::println);
System.out.println("将字符串分割求和:");
String str = "30,40,50,60,70";
System.out.println("mapToInt方式一:");
System.out.println(Stream.of(str.split(",")).mapToInt(x -> Integer.valueOf(x)).sum());
System.out.println("map+mapToInt方式二:");
System.out.println(Stream.of(str.split(",")).map(x -> Integer.valueOf(x)).mapToInt(x -> x).sum());
System.out.println("mapToInt Integer::valueOf方式三:");
System.out.println(Stream.of(str.split(",")).mapToInt(Integer::valueOf).sum());
System.out.println("map Integer::valueOf mapToInt方式四:");
System.out.println(Stream.of(str.split(",")).map(Integer::valueOf).mapToInt(x -> x).sum());
String str2 = "java,scala,C#,python";
Stream.of(str2.split(",")).map(x -> new Person(x)).forEach(System.out::println);
Stream.of(str2.split(",")).map(Person::new).forEach(System.out::println);
Stream.of(str2.split(",")).map(x -> Person.build(x)).forEach(System.out::println);
Stream.of(str2.split(",")).map(Person::build).forEach(System.out::println);
System.out.println("求和并且打印每个元素:");
System.out.println(Stream.of(str.split(",")).peek(System.out::println).mapToInt(Integer::valueOf).sum());
System.out.println("比较元素里面的值是否大于给定的数值:");
System.out.println(asList.stream().allMatch(x -> x >= 0));
System.out.println(asList.stream().allMatch(x -> x >= 11));
// asList.stream().flatMap(x->String.valueOf(x))
}
}