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单向,只能操作一次
官方介绍中的一个求最大值用法
* int sum = widgets.stream()
* .filter(w -> w.getColor() == RED)
* .mapToInt(w -> w.getWeight())
* .sum();
类图:
Api列表
Modifier and Type | Method and Description |
---|---|
boolean | allMatch(Predicate<? super T> predicate) Returns whether all elements of this stream match the provided predicate. |
boolean | anyMatch(Predicate<? super T> predicate) Returns whether any elements of this stream match the provided predicate. |
static <T> Stream.Builder<T> | builder() Returns a builder for a |
<R,A> R | collect(Collector<? super T,A,R> collector) Performs a mutable reduction operation on the elements of this stream using a |
<R> R | collect(Supplier<R> supplier, BiConsumer<R,? super T> accumulator, BiConsumer<R,R> combiner) Performs a mutable reduction operation on the elements of this stream. |
static <T> Stream<T> | concat(Stream<? extends T> a, Stream<? extends T> b) Creates a lazily concatenated stream whose elements are all the elements of the first stream followed by all the elements of the second stream. |
long | count() Returns the count of elements in this stream. |
Stream<T> | distinct() Returns a stream consisting of the distinct elements (according to |
static <T> Stream<T> | empty() Returns an empty sequential |
Stream<T> | filter(Predicate<? super T> predicate) Returns a stream consisting of the elements of this stream that match the given predicate. |
Optional<T> | findAny() Returns an |
Optional<T> | findFirst() Returns an |
<R> Stream<R> | flatMap(Function<? super T,? extends Stream<? extends R>> mapper) Returns a stream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element. |
DoubleStream | flatMapToDouble(Function<? super T,? extends DoubleStream> mapper) Returns an |
IntStream | flatMapToInt(Function<? super T,? extends IntStream> mapper) Returns an |
LongStream | flatMapToLong(Function<? super T,? extends LongStream> mapper) Returns an |
void | forEach(Consumer<? super T> action) Performs an action for each element of this stream. |
void | forEachOrdered(Consumer<? super T> action) Performs an action for each element of this stream, in the encounter order of the stream if the stream has a defined encounter order. |
static <T> Stream<T> | generate(Supplier<T> s) Returns an infinite sequential unordered stream where each element is generated by the provided |
static <T> Stream<T> | iterate(T seed, UnaryOperator<T> f) Returns an infinite sequential ordered |
Stream<T> | limit(long maxSize) Returns a stream consisting of the elements of this stream, truncated to be no longer than |
<R> Stream<R> | map(Function<? super T,? extends R> mapper) Returns a stream consisting of the results of applying the given function to the elements of this stream. |
DoubleStream | mapToDouble(ToDoubleFunction<? super T> mapper) Returns a |
IntStream | mapToInt(ToIntFunction<? super T> mapper) Returns an |
LongStream | mapToLong(ToLongFunction<? super T> mapper) Returns a |
Optional<T> | max(Comparator<? super T> comparator) Returns the maximum element of this stream according to the provided |
Optional<T> | min(Comparator<? super T> comparator) Returns the minimum element of this stream according to the provided |
boolean | noneMatch(Predicate<? super T> predicate) Returns whether no elements of this stream match the provided predicate. |
static <T> Stream<T> | of(T... values) Returns a sequential ordered stream whose elements are the specified values. |
static <T> Stream<T> | of(T t) Returns a sequential |
Stream<T> | peek(Consumer<? super T> action) Returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream. |
Optional<T> | reduce(BinaryOperator<T> accumulator) Performs a reduction on the elements of this stream, using an associative accumulation function, and returns an |
T | reduce(T identity, BinaryOperator<T> accumulator) Performs a reduction on the elements of this stream, using the provided identity value and an associative accumulation function, and returns the reduced value. |
<U> U | reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner) Performs a reduction on the elements of this stream, using the provided identity, accumulation and combining functions. |
Stream<T> | skip(long n) Returns a stream consisting of the remaining elements of this stream after discarding the first |
Stream<T> | sorted() Returns a stream consisting of the elements of this stream, sorted according to natural order. |
Stream<T> | sorted(Comparator<? super T> comparator) Returns a stream consisting of the elements of this stream, sorted according to the provided |
Object[] | toArray() Returns an array containing the elements of this stream. |
<A> A[] | toArray(IntFunction<A[]> generator) Returns an array containing the elements of this stream, using the provided |
功能:
流的操作类型分为两种:
- Intermediate :一个流可以后面跟随零个或多个 intermediate 操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用。这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始流的遍历。
- Terminal :一个流只能有一个 terminal 操作,当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。Terminal 操作的执行,才会真正开始流的遍历,并且会生成一个结果,或者一个 side effect。
还有一种操作被称为 short-circuiting 。用以指:
- 对于一个 intermediate 操作,如果它接受的是一个无限大(infinite/unbounded)的 Stream,但返回一个有限的新 Stream。
- 对于一个 terminal 操作,如果它接受的是一个无限大的 Stream,但能在有限的时间计算出结果。
使用:
对 Stream 的使用就是实现一个 filter-map-reduce 过程,产生一个最终结果,或者导致一个副作用(side effect)。
创建流:
// 1. Individual values
Stream stream1 = Stream.of("a", "b", "c");
// 2. Arrays
String [] strArray = new String[] {"a", "b", "c"};
Stream stream2 = Stream.of(strArray);
Stream stream3 = Arrays.stream(strArray);
// 3. Collections
List<String> list = Arrays.asList(strArray);
Stream stream4 = list.stream();
- intermediate:
主要操作map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
1.filter过滤,返回一个通过过滤值的stream
Stream<T> | filter(Predicate<? super T> predicate) Returns a stream consisting of the elements of this stream that match the given predicate. |
ArrayList<User> users = new ArrayList<>();
User user1 = new User("张三", 20, "男");
User user2 = new User("李四", 22, "女");
User user3 = new User("王五", 24, "男");
users.add(user1);
users.add(user2);
users.add(user3);
Stream<User> userStream = users.stream().filter(user -> user.getAge() == 20);
2.map构造映射
<R> Stream<R> | flatMap(Function<? super T,? extends Stream<? extends R>> mapper) Returns a stream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element. |
DoubleStream | flatMapToDouble(Function<? super T,? extends DoubleStream> mapper) Returns an |
IntStream | flatMapToInt(Function<? super T,? extends IntStream> mapper) Returns an |
LongStream | flatMapToLong(Function<? super T,? extends LongStream> mapper) Returns an |
<R> Stream<R> | map(Function<? super T,? extends R> mapper) Returns a stream consisting of the results of applying the given function to the elements of this stream. |
DoubleStream | mapToDouble(ToDoubleFunction<? super T> mapper) Returns a |
IntStream | mapToInt(ToIntFunction<? super T> mapper) Returns an |
LongStream | mapToLong(ToLongFunction<? super T> mapper) Returns a |
ArrayList<User> users = new ArrayList<>();
User user1 = new User("张三", 20, "男");
User user2 = new User("李四", 22, "女");
User user3 = new User("王五", 24, "男");
users.add(user1);
users.add(user2);
users.add(user3);
Stream<User> userStream = users.stream().filter(user -> user.getAge() == 20);
// 通过map对stream中的值进行映射
LongStream longStream = userStream.mapToLong(user -> user.getAge() *
user.getAge());
longStream.forEach(value -> System.out.println(value));
// 打印结果
400
其中,map是一对一的映射,flatMap是一对多的映射
3.distinct去重,并返回一个流
Stream<T> | distinct() Returns a stream consisting of the distinct elements (according to |
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 3);
integers.stream().distinct().forEach(System.out::println);
//打印结果
1
2
3
4
4.sorted按自然顺序排序,sorted(Comparator<? super T> comparator)按给定比较器排序,并返回一个流
Stream<T> | sorted() Returns a stream consisting of the elements of this stream, sorted according to natural order. |
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 3);
integers.stream().sorted().forEach(System.out::println);
// 打印结果
1
2
3
3
4
5. peek 窥视,偷看;微微露出,探出
This method exists mainly to support debugging, where you want to see the elements as they flow past a certain point in a pipeline:
此方法的存在主要是为了支持调试,您希望在元素流过管道中的某个点时看到它们
Stream<T> | peek(Consumer<? super T> action) Returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream. |
Stream.of("one", "two", "three", "four")
.filter(e -> e.length() > 3)
.peek(e -> System.out.println("Filtered value: " + e))
.map(String::toUpperCase)
.peek(e -> System.out.println("Mapped value: " + e))
.collect(Collectors.toList());
// 输出结果
Filtered value: three
Mapped value: THREE
Filtered value: four
Mapped value: FOUR
6. limit,截取指定数量元素的流。和mysql的limit类似
Stream<T> | limit(long maxSize) Returns a stream consisting of the elements of this stream, truncated to be no longer than |
虽然limit()通常是顺序流管道上的廉价操作,但在有序的并行管道上,它的开销可能相当大,特别是对于maxSize的大值,因为limit(n)被限制不只是返回任何n个元素,而是返回相遇顺序中的前n个元素。如果您的情况语义允许,使用无序流源(如generate(Supplier))或使用basestreamp .unordered()删除排序约束可能会导致并行管道中limit()的显著加速。如果需要与遇到顺序保持一致,并且在并行管道中使用limit()会导致性能低下或内存利用率低下,那么使用basestrear .sequential()切换到顺序执行可能会提高性能
Stream.of("one", "two", "three", "four").limit(2).forEach(System.out::println);
// 输出结果
one
two
7. skip 跳转,保留指定位置元素之后的流
Stream<T> | skip(long n) Returns a stream consisting of the remaining elements of this stream after discarding the first |
Stream.of("one", "two", "three", "four").skip(2).forEach(System.out::println);
// 打印结果
three
four
- Terminal:
主要操作:forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator
1.forEach
void | forEach(Consumer<? super T> action) Performs an action for each element of this stream. |
此操作的行为是显式的不确定性。对于并行流管道,此操作不能保证遵从流的相遇顺序,因为这样做会牺牲并行性的好处。对于任何给定的元素,操作可以在库选择的任何时间和线程中执行。如果操作访问共享状态,则负责提供所需的同步。
2.forEachOrdered、
void | forEachOrdered(Consumer<? super T> action) Performs an action for each element of this stream, in the encounter order of the stream if the stream has a defined encounter order. |
此操作一次处理一个元素,如果存在元素,则按相遇顺序处理。对一个元素执行操作发生在对后续元素执行操作之前,但是对于任何给定的元素,操作可以在库选择的任何线程中执行。
3. toArray、 返回一个包含流中元素的数组
Object[] | toArray() Returns an array containing the elements of this stream. |
<A> A[] | toArray(IntFunction<A[]> generator) Returns an array containing the elements of this stream, using the provided |
// 指定类型数组
Person[] men = people.stream()
.filter(p -> p.getGender() == MALE)
.toArray(Person[]::new);
// Object类型数组
Object[] objects = Stream.of("one", "two", "three", "four").toArray();
for (int i = 0; i < objects.length; i++) {
System.out.println(objects[i]);
}
4.reduce、 这个方法的主要作用是把 Stream 元素组合起来。它提供一个起始值(种子),然后依照运算规则(BinaryOperator),和前面 Stream 的第一个、第二个、第 n 个元素组合。
Optional<T> | reduce(BinaryOperator<T> accumulator) Performs a reduction on the elements of this stream, using an associative accumulation function, and returns an |
T | reduce(T identity, BinaryOperator<T> accumulator) Performs a reduction on the elements of this stream, using the provided identity value and an associative accumulation function, and returns the reduced value. |
<U> U | reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner) Performs a reduction on the elements of this stream, using the provided identity, accumulation and combining functions. |
Sum, min, max, average, and string concatenation are all special cases of reduction. Summing a stream of numbers can be expressed as:
Integer sum = integers.reduce(0, (a, b) -> a+b);
or:
Integer sum = integers.reduce(0, Integer::sum);
// 1
T result = identity;
for (T element : this stream)
result = accumulator.apply(result, element)
return result;
// 2
boolean foundAny = false;
T result = null;
for (T element : this stream) {
if (!foundAny) {
foundAny = true;
result = element;
}
else
result = accumulator.apply(result, element);
}
return foundAny ? Optional.of(result) : Optional.empty();
网上搜到的使用方式
// 字符串连接,concat = "ABCD"
String concat = Stream.of("A", "B", "C", "D").reduce("", String::concat);
// 求最小值,minValue = -3.0
double minValue = Stream.of(-1.5, 1.0, -3.0, -2.0).reduce(Double.MAX_VALUE, Double::min);
// 求和,sumValue = 10, 有起始值
int sumValue = Stream.of(1, 2, 3, 4).reduce(0, Integer::sum);
// 求和,sumValue = 10, 无起始值
sumValue = Stream.of(1, 2, 3, 4).reduce(Integer::sum).get();
// 过滤,字符串连接,concat = "ace"
concat = Stream.of("a", "B", "c", "D", "e", "F").
filter(x -> x.compareTo("Z") > 0).
reduce("", String::concat);
5.collect、 使用Collector把流转换成一个集合
<R,A> R | collect(Collector<? super T,A,R> collector) Performs a mutable reduction operation on the elements of this stream using a |
<R> R | collect(Supplier<R> supplier, BiConsumer<R,? super T> accumulator, BiConsumer<R,R> combiner) Performs a mutable reduction operation on the elements of this stream. |
// The following will accumulate strings into an ArrayList:
List<String> asList = stringStream.collect(Collectors.toList());
// The following will classify Person objects by city:
Map<String, List<Person>> peopleByCity
= personStream.collect(Collectors.groupingBy(Person::getCity));
// The following will classify Person objects by state and city, cascading two Collectors together:
Map<String, Map<String, List<Person>>> peopleByStateAndCity
= personStream.collect(Collectors.groupingBy(Person::getState,
Collectors.groupingBy(Person::getCity)));
// There are many existing classes in the JDK whose signatures are well-suited for use with method references as arguments to collect(). For example, the following will accumulate strings into an ArrayList:
List<String> asList = stringStream.collect(ArrayList::new, ArrayList::add,
ArrayList::addAll);
// The following will take a stream of strings and concatenates them into a single string:
String concat = stringStream.collect(StringBuilder::new, StringBuilder::append,
StringBuilder::append)
.toString();
6.min、 求最小值
Optional<T> | min(Comparator<? super T> comparator) Returns the minimum element of this stream according to the provided |
System.out.println(Stream.of("one", "two", "three", "four").allMatch(a -> a == "two"));
// 打印结果
false
7.max、 求最大值
Optional<T> | max(Comparator<? super T> comparator) Returns the maximum element of this stream according to the provided |
System.out.println(Stream.of("one", "two", "three", "four").max((x,y)->x.length()-y.length()));
System.out.println(Stream.of("one", "two", "three", "four").max(Comparator.comparingInt(String::length)));
// 打印结果
Optional[three]
Optional[three]
8.count、 计数
long | count() Returns the count of elements in this stream. |
System.out.println(Stream.of("one", "two", "three", "four").count());
// 打印结果
4
9.anyMatch、 任何一个匹配返回true
boolean | anyMatch(Predicate<? super T> predicate) Returns whether any elements of this stream match the provided predicate. |
System.out.println(Stream.of("one", "two", "three", "four").anyMatch(a->a=="two"));
// 打印结果
true
10.allMatch、 所有都匹配返回true
boolean | allMatch(Predicate<? super T> predicate) Returns whether all elements of this stream match the provided predicate. |
System.out.println(Stream.of("one", "two", "three", "four").allMatch(a->a.length()<6));
// 打印结果
true
11.noneMatch、 没有匹配返回true
boolean | noneMatch(Predicate<? super T> predicate) Returns whether no elements of this stream match the provided predicate. |
System.out.println(Stream.of("one", "two", "three", "four").noneMatch(a->a=="two"));
// 打印结果
false
12.findFirst、查询第一个元素
Optional<T> | findFirst() Returns an |
System.out.println(Stream.of("one", "two", "three", "four").findFirst());
// 打印结果
Optional[one]
13.findAny、
findAny具有不确定性,可以选中任意元素,目的是在并行流中追求最大性能,如果需要稳定性,使用findFirst()
Optional<T> | findAny() Returns an |
System.out.println(Stream.of("one", "two", "three", "four").findAny());
// 测试固定返回第一个
Optional[one]
System.out.println(Arrays.asList("one", "two", "three", "four","five").parallelStream().findAny());
// 测试固定返回第三个
Optional[three]
14.iterate根据seed和UnaryOperator操作生成一个流
static <T> Stream<T> | iterate(T seed, UnaryOperator<T> f) Returns an infinite sequential ordered |
Stream.iterate(0, n -> n + 2).limit(10).forEach(System.out::println);
//生成一个等差数列
0
2
4
6
8
10
12
14
16
18
- Short-circuiting:
主要操作:anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit
BaseStream中的方法:close, isParallel, iterator, onClose, parallel, sequential, spliterator, unordered