A java.util.Stream
represents
a sequence of elements on which one or more operations can be performed. Stream operations are either intermediate or terminal.
While terminal operations return a result of a certain type, intermediate operations return the stream itself so you can chain multiple method calls in a row. Streams are created on a source, e.g. a java.util.Collection
like
lists or sets (maps are not supported). Stream operations can either be executed sequential or parallel.
stream 表示一個序列,在這個序列上可以執行一個或多個操作。流操作分爲中間操作和最終操作兩類,最終操作返回一個特定類型的結果,中間結果返回流對象,這樣可以在同一行鏈式調用多個方法。創建stream要指定數據源,collection 例如list 、set(不支持map)。stream操作可以串行、也可以並行。
List<String> stringCollection = new ArrayList<>();
stringCollection.add("ddd2");
stringCollection.add("aaa2");
stringCollection.add("bbb1");
stringCollection.add("aaa1");
stringCollection.add("bbb3");
stringCollection.add("ccc");
stringCollection.add("bbb2");
stringCollection.add("ddd1");
stream 可以通過Collection.stream()
or Collection.parallelStream()
創建。
Filter
Filter accepts a predicate
to filter all elements of the stream. This operation is intermediatewhich
enables us to call another stream operation (forEach
) on the result. ForEach accepts a consumer to be executed for each
element in the filtered stream. ForEach is a terminal operation. It's void
, so we cannot call another stream operation.
Filter 接受一個謂詞過濾stream裏的所有元素。filter是中間操作,其結果可以調用另一個操作。forEach 接受一個函數【函數式接口Consumer】,操作流對象裏的每一個元素。forEach是最終操作。不能再調用另一個流操作。
// aaa2 aaa1
stringCollection.stream().filter((s) -> s.startsWith("a")).forEach(System.out::println);
Sorted
Comparator
. // "aaa1", "aaa2"
stringCollection.stream().sorted().filter((s) -> s.startsWith("a")).forEach(System.out::println);
Keep in mind that sorted
does
only create a sorted view of the stream without manipulating the ordering of the backed collection. The ordering of stringCollection
is
untouched:stringCollection
不會被修改。 // ddd2, aaa2, bbb1, aaa1, bbb3, ccc, bbb2, ddd1
System.out.println(stringCollection);
Map
The intermediate operation map
converts each element into another object via the given function. The following example converts each string into an upper-cased string. But you can also use map
to
transform each object into another type. The generic type of the resulting stream depends on the generic type of the function you pass to map
.
// "DDD2", "DDD1", "CCC", "BBB3", "BBB2", "AAA2", "AAA1"
stringCollection.stream().map(String::toUpperCase).sorted((a, b) -> b.compareTo(a))
.forEach(System.out::println);
Match
Various matching operations can be used to check whether a certain predicate matches the stream. All of those operations are terminal and return a boolean result.
提供各種match匹配操作,用於檢查指定的predicate是否匹配整個stream。所有的這些匹配操作是最終操作,返回boolean結果。 boolean anyStartsWithA = stringCollection.stream().anyMatch((s) -> s.startsWith("a"));
System.out.println(anyStartsWithA); // true
boolean allStartsWithA = stringCollection.stream().allMatch((s) -> s.startsWith("a"));
System.out.println(allStartsWithA); // false
boolean noneStartsWithZ = stringCollection.stream().noneMatch((s) -> s.startsWith("z"));
System.out.println(noneStartsWithZ); // true
Count
Count is a terminal operation returning the number of elements in the stream as a long
.
count是一個最終操作,返回stream中的元素個數,返回值是long類型。
long startsWithB = stringCollection.stream().filter((s) -> s.startsWith("b")).count();
System.out.println(startsWithB); // 3
Reduce 簡化|規約 翻譯都不好
This terminal operation performs a reduction on the elements of the stream with the given function. The result is an Optional
holding the reduced value.
reduce操作是對流上的元素根據指定的函數執行reduction操作。結果是Optional,保存簡化後的結果。
Optional<String> reduced = stringCollection.stream().sorted().reduce((s1, s2) -> s1 + "#" + s2);
// "aaa1#aaa2#bbb1#bbb2#bbb3#ccc#ddd1#ddd2"
reduced.ifPresent(System.out::println);
ParallelStream
As mentioned above streams can be either sequential or parallel. Operations on sequential streams are performed on a single thread while operations on
parallel streams are performed concurrent on multiple threads.
stream可以是串行也可以是並行的。串行stream單線程執行的,並行stream是多線程並行執行的。
public class ParallelStreamTest {
public static void main(String[] args) {
int max = 1000000;
List<String> values = new ArrayList<>(max);
for (int i = 0; i < max; i++) {
UUID uuid = UUID.randomUUID();
values.add(uuid.toString());
}
long t0 = System.nanoTime();
long count = values.stream().sorted().count();
System.out.println(count);
long t1 = System.nanoTime();
long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
System.out.println(String.format("sequential sort took: %d ms", millis));
long t2 = System.nanoTime();
long count2 = values.parallelStream().sorted().count();
System.out.println(count2);
long t3 = System.nanoTime();
long millis2 = TimeUnit.NANOSECONDS.toMillis(t3 - t2);
System.out.println(String.format("parallel sort took: %d ms", millis2));
}
}
結果大概差 50%。
1000000
sequential sort took: 1271 ms
1000000
parallel sort took: 560 ms