JDK1.8-Stream API使用

一、前言

??在目前用到的JDK8的功能當(dāng)中,毫無疑問Stream的使用是最多的,所以通過這篇文章來學(xué)習(xí)總結(jié)一下。
??首先,Java8的Stream是對集合對象操作的API,它專注于對集合對象進(jìn)行各種非常便利,高效的聚合操作或者大批量操作,從而減少代碼的復(fù)雜度。借助于lambda表達(dá)式,極大的提高編程效率和程序可讀性。并且Stream支持串行和并行兩種模式,使我們無需編寫太多代碼,就可以很方便的寫出高性能的并發(fā)程序。

二、Stream結(jié)構(gòu)及構(gòu)建

public interface Stream<T> extends BaseStream<T, Stream<T>>
public interface BaseStream<T, S extends BaseStream<T, S>>
    extends AutoCloseable { {

可以看到,Stream繼承自BaseStream接口,而BaseStream又繼承自AutoCloseable接口,顧名思義,AutoCloseable負(fù)責(zé)流的自動關(guān)閉。

我們這里來了解下生成Stream的幾種常用方式:

// 1. 借助Stream的of方法
Stream stream = Stream.of("a", "b", "c");
String [] strArray = new String[] {"a", "b", "c"};
// 2. 通過數(shù)組生成Stream
stream = Stream.of(strArray);
stream = Arrays.stream(strArray);
// 3. 通過集合來生成Stream
List<String> list = Arrays.asList(strArray);
stream = list.stream();

而對于基礎(chǔ)數(shù)值類型,目前提供了三種對應(yīng)的包裝類型Stream:IntStream,LongStreamDoubleStrem,當(dāng)然我們也可以使用 Stream<Integer>Stream<Long>、Stream<Double>,但是 boxing 和 unboxing 會很耗時,所以特別為這三種基本數(shù)值型提供了對應(yīng)的 Stream。

三、Stream使用

先說下Stream的類型,Stream一般情況下包含了兩個類型:中間操作(Intermediate)和結(jié)束操作(Terminal):

  1. Intermediate,所謂的中間操作,就是說每次調(diào)用做一些處理之后會返回一個新的Stream,這類操作都是惰性的,也就是說并沒有真正開始流的遍歷。這些操作包括:map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel等;
  2. Terminal,一個Stream只能執(zhí)行一次結(jié)束操作,而且只能是最后一個操作,執(zhí)行terminal之后,Stream被消費(fèi)掉了,并且產(chǎn)生了一個結(jié)果,這些操作包括:forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny等;

??再簡單說下Stream流的特點(diǎn),Stream其實(shí)有點(diǎn)類似于迭代器,每個Stream只能操作一次,操作過之后就不能再操作該對象了,也就是一種單向的,不可重復(fù)操作的對象。

2. map方法

該方法的作用就是將input Stream的每一個元素,按照一定規(guī)則處理之后,映射成output Stream的另一個元素,相當(dāng)于一對一的輸入輸出,平時的時候該方式使用較多。比如我們將字符串?dāng)?shù)組中所有的對象轉(zhuǎn)為大寫:

List<String> list = Arrays.asList("stream", "map");
Stream<String> stream = list.stream();
List<String> newList = stream.map(input -> input.toUpperCase()).collect(Collectors.toList());

因?yàn)镾tream只能使用一次,如果我們再操作的話就是拋出異常:

List<String> newList = stream.map(input -> input.toUpperCase()).collect(Collectors.toList());
newList = stream.map(input -> input.toLowerCase()).collect(Collectors.toList());
Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
    at java.util.stream.AbstractPipeline.<init>(AbstractPipeline.java:203)
    at java.util.stream.ReferencePipeline.<init>(ReferencePipeline.java:94)
    at java.util.stream.ReferencePipeline$StatelessOp.<init>(ReferencePipeline.java:618)
    at java.util.stream.ReferencePipeline$3.<init>(ReferencePipeline.java:187)
    at java.util.stream.ReferencePipeline.map(ReferencePipeline.java:186)
3. mapToInt/mapToLong/mapToDouble方法

顧名思義,這就是將對應(yīng)的Stream轉(zhuǎn)為IntStream,LongStream,DoubleStream

List<Integer> list = Arrays.asList(100, 200);
IntStream intStream = list.stream().mapToInt(input -> input);
4. flatMap方法

前面說過的map方法是一對一的輸入輸出,而flatMap方法則是一種一對多的映射關(guān)系。

Stream<List<Integer>> inputStream = Stream.of(
        Arrays.asList(1),
        Arrays.asList(2, 3),
        Arrays.asList(4, 5, 6)
);
Stream<Integer> outputStream = inputStream.flatMap((childList) -> childList.stream());
List<Integer> list = outputStream.collect(Collectors.toList());
System.out.println(list);
[1,2,3,4,5,6]

flatMap 是對input Stream 中的層級進(jìn)行結(jié)構(gòu)扁平化,就是將最底層元素抽出來放到一起,最終 output 的新 Stream 里面都是單個的數(shù)字。我們再來簡單看下map方法的對應(yīng)實(shí)現(xiàn):

// inputStream不變
Stream<Stream<Integer>> stream = inputStream.map(childList -> childList.stream());
List<List<Integer>> list = stream.map(input -> input.collect(Collectors.toList())).collect(Collectors.toList());
System.out.println(list);
[[1], [2, 3], [4, 5, 6]]

從這里可以大致看出它們的區(qū)別,對于flatMap來說,它的輸入輸出大致如下:

{{1,2},{3,4},{5,6}}  -> flatMap  -> {1,2,3,4,5,6}

而對map方法來說,則是:

{{1,2},{3,4},{5,6}}  -> map -> {1,2}, {3,4},{5,6}
5. filter方法

該方法用于對Stream中的元素按照某些條件進(jìn)行過濾,過濾后的元素生成一個新的元素,比如過濾數(shù)組中的偶數(shù):

Integer[] sixNums = {1, 2, 3, 4, 5, 6};
Stream.of(sixNums).filter(n -> (n % 2 == 0)).forEach(num -> System.out.print(num + " "));
2 4 6 
6. foreach方法

類似于for循環(huán),用于遍歷Stream中的每個元素,比較簡單,可能需要注意的是,forEach 不能修改自己包含的本地變量值,也不能使用 break/return 之類的關(guān)鍵字提前結(jié)束循環(huán):

Stream<String> stream = Stream.of("hello", "world");
// 方式1
stream.forEach(num -> System.out.print(num));
// 方式2
stream.forEach(System.out::print);
7. findFirst

返回Stream對象的第一個元素,由于返回的是Optional,所以返回的值有可能為空:

Stream<String> stream = Stream.of("hello", "world");
Optional<String> optional = stream.findFirst();
String name = optional.map(String::toLowerCase).orElse("");
System.out.println(name);

Optional是jdk8提供的一種用于優(yōu)雅的解決 NullPointExecption 的方式,等下篇文章我們來學(xué)習(xí)一下。

8. reduce方法

這個方法的作用主要是把Stream中的元素組合起來,比如說字符串拼接,數(shù)值類型的求和等都是特殊的reduce操作,并且我們可以根據(jù)重載方法選擇是否有初始值。

// 字符串連接,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);
// 求和的另一種形式
int sum = Stream.of(1, 2, 3, 4).reduce(0, (a,b) -> a+b);
// 求和,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);

上面代碼例如第一個示例的 reduce(),第一個參數(shù)(空白字符)即為起始值,第二個參數(shù)(String::concat)為 BinaryOperator,這類有起始值的 reduce() 都返回具體的對象。而對于第四個示例沒有起始值的 reduce(),返回的是 Optional,請留意這個區(qū)別。

9. limit/skip方法

limit方法用于返回Stream元素的前n個元素,而skip方法是跳過前n個元素返回剩余的元素:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
list.stream().limit(8).forEach(System.out::print);
System.out.println();
list.stream().limit(8).skip(3).forEach(System.out::print);
12345678
45678
10. sorted

sorted方法是用于對Stream元素進(jìn)行排序的,我們可以按照默認(rèn)的自然排序規(guī)則進(jìn)行排序, 也可以指定具體的比較器來進(jìn)行排序:

Stream<T> sorted();
Stream<T> sorted(Comparator<? super T> comparator);

Stream的sorted方法比數(shù)組的排序更強(qiáng)之處在于,你可以首先對 Stream 進(jìn)行各類 map、filter、limit、skip操作之后再進(jìn)行排序:

List<Integer> list = Arrays.asList(5, 7, 1, 4, 2, 6, 3, 8, 9, 10);
list.stream().limit(5).sorted().forEach(System.out::print);
System.out.println();
list.stream().limit(5).sorted(Comparator.reverseOrder()).forEach(System.out::print);
12457
75421
11. min/max/distinct方法

min 和 max 的功能也可以通過對 Stream 元素先排序,再 findFirst 來實(shí)現(xiàn),但前者的性能會更好,為 O(n),而 sorted 的成本是 O(n log n)。我們來看一下獲取最小值的方式:

List<Integer> list = Arrays.asList(5, 7, 1, 4, 2, 6, 3, 8, 9, 10);
// 通過Stream的min方法
Integer min2 = list.stream().min(Comparator.naturalOrder()).get();
// 通過IntStrem的min方法
Integer min1 = list.stream().mapToInt(input -> input).min().getAsInt();

而distinct方法是用于過濾重復(fù)數(shù)據(jù)的:

List<Integer> list = Arrays.asList(5, 7, 1, 7, 2, 6, 3, 9, 9, 10);
list.stream().distinct().forEach(System.out::print);
571263910
12. allMatch/anyMatch/noneMatch方法
  • allMatch, 對Stream中的所有元素進(jìn)行判斷,全部滿足條件的時候返回true,只要有一個不符合條件就返回false;
  • anyMatch,Stream中只要有一個滿足條件,就返回true;
  • noneMatch,Stream中沒有一個元素滿足條件,這時返回true;
List<Integer> list = Arrays.asList(5, 7, 1, 7, 2, 6, 3, 9, 9, 10);
boolean isAllRight = list.stream().allMatch(input -> (input > 0));
boolean isAnyRight = list.stream().anyMatch(input -> (input > 2));
boolean isNoneRight = list.stream().noneMatch(input -> (input < 0));
System.out.println("isAllRight:" + isAllRight + " isAnyRight:" + isAnyRight + " isNoneRight:" + isNoneRight);
isAllRight:true isAnyRight:true isNoneRight:true
13. peek方法

??peek方法,會生成一個包含原Stream的所有元素的新Stream,同時會提供一個消費(fèi)函數(shù)(Consumer實(shí)例),新Stream每個元素被消費(fèi)的時候都會執(zhí)行給定的消費(fèi)函數(shù)。比如說foreach方法是一個terminal 操作,執(zhí)行之后,Stream就消費(fèi)掉了,我們無法對一個Stream進(jìn)行兩次操作,而peek方法作為intermediate 操作,則可以達(dá)到類似的目的:

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

如上,我們可以在遍歷列表的時候,先打印字符串,再將該字符串轉(zhuǎn)成大寫再打印出來。

另外,根據(jù)API的說明,該方法主要用于調(diào)試,方便debug查看Stream內(nèi)進(jìn)行處理的每個元素。

14. forEachOrdered方法

??forEachOrdered方法和 forEach 方法功能一樣,都是用于遍歷Stream,不同的地方在于并行流的處理上。并行的時候 forEach 方法為了效率,它的順序和Stream元素的順序不一定完全一樣,而forEachOrdered 方法的順序則是和Stream元素的順序是一樣的。

List<String> list = Arrays.asList("x", "y", "z");

list.parallelStream().forEach(x -> System.out.print(" " + x));
System.out.println();
list.parallelStream().forEachOrdered(x -> System.out.print(" " + x));
System.out.println();

//輸出的順序不一定(效率更高)
Stream.of("AAA", "BBB", "CCC").parallel().forEach(s -> System.out.print(" " + s));
System.out.println();
//輸出的順序與元素的順序嚴(yán)格一致
Stream.of("AAA", "BBB", "CCC").parallel().forEachOrdered(s -> System.out.print(" " + s));
 y x z
 x y z
 BBB CCC AAA
 AAA BBB CCC
15. toArray方法

這個方法比較簡單,就是返回對應(yīng)的數(shù)組,該方法默認(rèn)是返回Object數(shù)組,不過我們可以使用它的重載方法返回對應(yīng)格式的數(shù)組:

Object[] toArray();
<A> A[] toArray(IntFunction<A[]> generator);

對應(yīng)例子:

List<String> list = Arrays.asList("x", "y", "z");
Object[] objects = list.stream().toArray();
Integer[] arrays = list.stream().toArray(Integer[]::new);
16. count方法

count方法表示獲取Stream流中元素的數(shù)量,返回long類型:

// 打印 4 
long num = Stream.of(1, 2, 3, 4).count();
// 打印 3
long num = Stream.of(1, 2, 3, 4).limit(3).count();
17. findAny方法

findAny方法表示從流中隨便選擇一個元素,該方法返回的值是不穩(wěn)定的:

Integer num = Stream.of(1, 2, 3, 4).findAny().get();
18. collect方法

collect方法我們前面已經(jīng)接觸過,有兩個方法,我們先看一下簡單的那個:

<R, A> R collect(Collector<? super T, A, R> collector);

在前文中,我們使用map方法對流進(jìn)行處理之后,返回的還是一個Stream,而此時我們是無法我們的集合操作的,這時候就需要將流重新轉(zhuǎn)換為集合框架中對應(yīng)的集合,那么這時候我們就可以通過該方法來實(shí)現(xiàn):

List<String> list = Arrays.asList("hello", "world").stream().collect(Collectors.toList());

該方法接收一個Collector類型的參數(shù),但幸運(yùn)的是Java8給我們提供了Collector的工具類:Collectors,這其中已經(jīng)定義了一些靜態(tài)工廠方法,比如Collectors.toCollection() 生成集合,Collectors.toList()生成List,Collectors.toSet() 生成Set等,Collectors是個很好的工具類,封裝了許多操作,后續(xù)我們再來介紹。

接下來,再簡單看下該方法的另一個重載方法:

<R> R collect(Supplier<R> supplier,
      BiConsumer<R, ? super T> accumulator,
      BiConsumer<R, R> combiner);

該方法比較復(fù)雜,我們先簡單分析下,等以后如果用到了,再來仔細(xì)研究。該方法有三個參數(shù):Supplier supplier是一個工廠函數(shù),用來生成一個新的容器;BiConsumer accumulator也是一個函數(shù),用來把Stream中的元素添加到結(jié)果容器中;BiConsumer combiner還是一個函數(shù),用來把中間狀態(tài)的多個結(jié)果容器合并成為一個(并發(fā)的時候會用到)。來簡單看一下例子吧:

List<Integer> nums = Arrays.asList(1, 1, null, 2, 3, 4, null, 5, 6, 7, 8, 9, 10);
List<Integer> numsWithoutNull = nums.stream().filter(num -> num != null).
        collect(() -> new ArrayList<Integer>(),
                (list, item) -> list.add(item),
                (list1, list2) -> list1.addAll(list2));

使用方法引用來優(yōu)化下該例子:

List<Integer> nums = Arrays.asList(1, 1, null, 2, 3, 4, null, 5, 6, 7, 8, 9, 10);
List<Integer> numsWithoutNull = nums.stream().filter(num -> num != null).
        collect(ArrayList::new, ArrayList::add, ArrayList::addAll);

接下來,說下該方法:該方法是將一個Integer類型的List,先過濾掉為null的元素,然后把剩下的元素放到新的List中。再來看一下這些參數(shù):

    1. 第一個函數(shù)生成一個新的ArrayList實(shí)例;
    1. 第二個函數(shù)接受兩個參數(shù),第一個是前面生成的ArrayList對象,第二個是stream中包含的元素,函數(shù)體就是把stream中的元素加入ArrayList對象中。第二個函數(shù)被反復(fù)調(diào)用直到原stream的元素被消費(fèi)完畢;
    1. 第三個函數(shù)也是接受兩個參數(shù),這兩個都是ArrayList類型的,函數(shù)體就是把第二個ArrayList全部加入到第一個中;

這么來看,這個方法是有點(diǎn)復(fù)雜,并且單看這個例子的話,是完全可以使用上面那個重載方法然后借助Collectors.toList來實(shí)現(xiàn)的。對這個方法的了解就到這了,等以后如果用到了,再來更新。

接下來是Stream的靜態(tài)方法,這些靜態(tài)方法目的都是為了創(chuàng)建Stream流。

1. of方法

Stream的of方法用來構(gòu)建有序的Stream對象,有兩個方法,提供單個對象及多個對象的構(gòu)建:

public static<T> Stream<T> of(T t)
public static<T> Stream<T> of(T... values) 

比如說:

Stream stream = Stream.of("a");
IntStream intStream= IntStream.of(1, 2, 3);
2. builder方法

??通過使用Stream.builder方法生成Builder對象,Builder對象是Stream的可變構(gòu)造器,也稱為流構(gòu)造器,該對象允許單獨(dú)生成元素并添加到構(gòu)造器,然后來生成流,來避免使用ArrayList作為臨時緩沖區(qū)產(chǎn)生的復(fù)制開銷。
??流構(gòu)建器有一個生命周期,它從一個構(gòu)建階段開始,在這個階段中可以添加元素,然后過渡到一個構(gòu)建階段,在這個階段之后,可能不會添加元素。構(gòu)建階段從調(diào)用build()方法開始,該方法創(chuàng)建一個有序流,其元素是按照添加到流構(gòu)建器的順序添加到流構(gòu)建器的元素。

Stream.Builder builder = Stream.builder();
builder.accept("hello");
builder.add("world");
Stream stream = builder.build();
stream.forEach(input -> System.out.print(input + " "));

//或者
Stream<String> streamBuilder = Stream.<String>builder().add("hello").add("world").build();
hello world 
3. empty方法

創(chuàng)建一個不包含任何元素的有序的Stream流:

Stream<Integer> stream = Stream.empty();
4. iterate方法

Stream的iterate方法和reduce方法有點(diǎn)像,接受一個種子值,和一個 UnaryOperator(例如 f),然后種子值成為 Stream 的第一個元素,f(seed) 為第二個,f(f(seed)) 第三個,以此類推:

// 比如生成等差數(shù)列 0 3 6 9 12 15 18 21 24 27 
Stream.iterate(0, n -> n + 3).limit(10). forEach(x -> System.out.print(x + " "));

同樣,iterate也是無限的,在進(jìn)行iterate的時候,必須要有l(wèi)imit這樣的操作來限制大小,但iterate生成的Stream是連續(xù)且有序的。

5. generate方法

??通過實(shí)現(xiàn) Supplier 接口,我們可以自己來控制流的生成,這種情形通常用于隨機(jī)數(shù)、常量的 Stream,把 Supplier 實(shí)例傳遞給 Stream.generate() ,這種生成的 Stream流是無限的,所以我們必須使用limit等方法來限制Stream的大小,并且通過generate方法生成的Stream是無序的;

// 生成10個隨機(jī)數(shù)
Stream.generate(new Random()::nextInt).limit(10).forEach(System.out::println);
//另外一種方式
IntStream.generate(() -> (int) (System.nanoTime() % 100)).limit(10).forEach(System.out::println);
6. concat方法

返回兩個Stream流連接的流:

public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) 
Stream<Integer> stream1 = Stream.of(1, 2, 3, 4);
Stream<Integer> stream2 = Stream.of(5, 6, 7, 8);
Stream.concat(stream1, stream2).forEach(System.out::print);

四、IntStream LongStream DoubleStream補(bǔ)充

因?yàn)檫@三個Stream中的操作屬于數(shù)值操作,所以它們中有些方法Stream中并沒有,我們也來簡單介紹下。由于這三個Stream都差不多,我們就以IntStream來進(jìn)行舉例。

1. sum/min/max/count/average方法

min,max,count方法Stream中都有,只不過在IntStream中這些方法的參數(shù)和返回值可能和Stream方法的返回值有稍許的不同,不過功能是一樣的。

// 計算min
IntStream.of(1, 2, 3, 4).min().getAsInt();
IntStream.of(1, 2, 3, 4).reduce(0, Integer::min);

// 計算max
IntStream.of(1, 2, 3, 4).max().getAsInt();
IntStream.of(1, 2, 3, 4).reduce(0, Integer::max);

sum方法的話,就是用于計算Stream中元素值的和,同樣也可也使用reduce方法來代替:

int sum = IntStream.of(1, 2, 3, 4).sum();
int sum = IntStream.of(1, 2, 3, 4).reduce(0, Integer::sum);

而average方法是用于計算平均值的,返回的是OptionalDouble類型:

// 計算平均值
double average = IntStream.of(1, 2, 3, 4).average().getAsDouble();
2. summaryStatistics方法

該方法用于獲取Stream流的各項(xiàng)匯總數(shù)據(jù),我們直接看例子就明白了:

// 各種計算值的匯總數(shù)據(jù)
IntSummaryStatistics summaryStatistics = IntStream.of(1, 2, 3, 4).summaryStatistics();
// 平均值,元素個數(shù),最大值,最小值,總和
System.out.println(summaryStatistics.getAverage());
System.out.println(summaryStatistics.getCount());
System.out.println(summaryStatistics.getMax());
System.out.println(summaryStatistics.getMin());
System.out.println(summaryStatistics.getSum());
3. asLongStream/asDoubleStream方法

這兩個方法比較簡單,就是轉(zhuǎn)為對應(yīng)的LongStream流和DoubleStream流。

4. boxed方法

基礎(chǔ)類型的裝箱操作,比如將int類型裝箱稱為Integer類型:

Stream<Integer> stream = IntStream.of(1, 2, 3, 4).boxed();
5. range方法

range方法是IntStream中的靜態(tài)方法,用于構(gòu)建某段范圍的IntStream流:

public static IntStream range(int startInclusive, int endExclusive) 

創(chuàng)建的Stream流包含開始值 startInclusive(inclusive),但不包含結(jié)束值 endExclusive(exclusive):

IntStream intStream = IntStream.range(1, 5);
// 1 2 3 4 
intStream.forEach(x -> System.out.print(x + " "));
6. rangeClosed方法

rangeClosed方法和range方法唯一的不同就是,創(chuàng)建的Stream流既包含開始值,又包含結(jié)束值,這點(diǎn)從參數(shù)命名上就可以知道。不得不說,該方法參數(shù)的命名很規(guī)范,值得我們學(xué)習(xí):

public static IntStream rangeClosed(int startInclusive, int endInclusive)

對應(yīng)的實(shí)例:

IntStream intStream = IntStream.rangeClosed(1, 5);
// 1 2 3 4 5 
intStream.forEach(x -> System.out.print(x + " "));

五、BaseStream中的方法

上面忘了說了,BaseStream作為Stream的底層接口,有幾個方法值得了解一下:

1. parallel方法

返回一個并行的且等效流,可能返回該流本身,因?yàn)樵揝tream已經(jīng)是并行的,或者該Stream的底層狀態(tài)被修改為了并行。

2. isParallel方法

判斷該Stream是否是并行的:

IntStream intStream = IntStream.rangeClosed(1, 5);
// false
boolean isParallel = intStream.isParallel();
// true
isParallel = intStream.parallel().isParallel();
3. iterator/spliterator方法

這兩個方法就比較簡單了,iterator就是返回迭代器對象,而spliterator則是返回一個并行的迭代器對象;

4. unordered方法

??返回一個無序的等效的Stream,可能返回的是Stream本身,因?yàn)樵揝tream已經(jīng)是無序的,或者該Stream的底層狀態(tài)被修改為了無序。當(dāng)不考慮流的順序時,可以使用無序的Stream來進(jìn)行操作,這樣可以加快一些方法的執(zhí)行速度,提高一些性能,一般用于并行的時候。對于unordered方法有個小問題可參考:https://stackoverflow.com/questions/21350195/stream-ordered-unordered-problems/38038578
https://coderanch.com/t/692966/certification/unordered-streams

本文參考自:
官方Api
Java 8 中的 Streams API 詳解
Java8初體驗(yàn)(二)Stream語法詳解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容