java 8 Stream,Optional的流庫詳解

java爬坑中發表於2020-09-26

1.從迭代到流的操作

流 你可以理解成比集合更高階的一個api,提供了很多有用的方法…

1. Stream的兩種 stream() | parallelStream()

		List<String> strList = Arrays.asList("a", "b", "c", "d", "e");
		
        strList.stream().forEach(System.out::print);
        
        strList.parallelStream().forEach(System.out::print);
//列印結果
abcde
----------
cdeab

:stream() | parallelStream()區別
stream()是按照集合順序,parallelStream()是並行處理,所以當你對流的操作不需要順序這個需求時,例如:求和, 求平均值,過濾,最大值等,優先考慮 parallelStream


2. foreach()

		List<String> strList = Arrays.asList("a", "b", "c", "d", "e");
		
        strList.stream().forEach(System.out::print);
//列印結果
abcde

:foreach()
和List的foreach差不多 ,遍歷出所有的元素


3. count()

List<String> strList = Arrays.asList("a", "b", "c", "d", "e");
long count = strList.stream().count();

//列印結果
5

:count()
和List的size()差不多 ,產生流中元素的數量,是個終止操作(可以理解為返回型別不是Stream)


2.流的建立

1. Stream.of(T… values)

		Integer[] ints = {1, 2, 3, 4, 5};
        Stream<Integer> integerStream1 = Stream.of(ints);
        integerStream1.forEach(System.out::print);
        System.out.println();
        System.out.println("----------");
        Stream<Integer> integerStream2 = Stream.of(1, 2, 3, 4, 5);
        integerStream2.forEach(System.out::print);
        System.out.println();
        System.out.println("----------");
        Stream<Integer> integerStream3 = Arrays.stream(ints, 1, 3);
        integerStream3.forEach(System.out::print);
//列印結果
12345
----------
12345
----------
23

注: 流的建立, 在操作力已經有collection裡的stream()方法,這個靜態方法可變長引數,
對於陣列 還可以擷取


2. Stream.empty()

**注:**  建立了一個不含任何元素的流, 相當於new了一個集合一樣,裡面啥都沒有

3. Stream.generate()

		Stream<String> s = Stream.generate(() -> "a").limit(5);
        //會生成 aaaaaaaaaaaa.........無線下去

注: generate() 傳參是一個提供商(Supplier)然後生成一個無線元素的流


4. Stream.iterate()

		Stream<Integer> iterate = Stream.iterate(5, n -> n < 10, n -> n + 1);
        iterate.forEach(System.out::print);
//列印結果
56789

注: 相對於generate(), 你給定一個的引數 然後後續元素是基於這個引數生成, 並且可以加一個限定條件
引數一:給定單數 (種子)
引數二:後續生成元素必須符合的條件,斷言,(引數二可不寫)
引數三:對於給定引數進行操作生成新的元素


5. Stream.ofNullable(T)

		List<String> strList = Arrays.asList("a", "b", "c", "d", "e");
        Stream<List<String>> strStream = Stream.ofNullable(strList);
        strStream.forEach(System.out::print);
//列印結果
[a, b, c, d, e]

注: ofNullable(T) 相對於它可以在T物件為null時返回 返回一個空的流,如果不為null,返回質保函一個元素(該元素就是T )的流,這個流的元素不是 5 個, 而是一整個List, 所以通常與flatMap相結合


3.filter、map和flatMap方法

概念: 流的轉換會產生一個新的流,它的元素派生自另一個流的元素。

1. filter()

 		Integer[] ints = {1, 2, 3, 4, 5};
        Stream<Integer> ints1 = Stream.of(ints);
        ints1.filter(integer -> integer > 2).forEach(System.out::print);
//列印結果
345

注: filter() 裡的引數是斷言, 你提供一個條件, 之後會返回一個滿足該條件元素的流


2. map()

		Integer[] ints = {1, 2, 3, 4, 5};
        Stream<Integer> ints1 = Stream.of(ints);
        ints1.map(integer -> integer + 2).forEach(System.out::print);
//列印結果
34567

注: map() 是按照某種方式轉化流種的值使用map()時,會有一個函式應用到每個元素上,並且將處理完的結果的所有元素重寫放到一個流中
用於物件時有個疑問

//假如有個集合List<Banner> banners 裡面有好多元素

//錯誤寫法
//有時會認為 把banner這個物件set一個值之後放到新的流中,但是是錯的,因為banner.setStatus()返回值是void
Stream<Banner> collect = banners.stream()
						.map(banner -> {
							banner.setStatus(BannerVO.STATUS_2);
						});

//正確寫法(為了好熟悉邏輯這樣寫,有好多種方法)
Stream<Banner> collect = banners.stream()
						.map(banner -> {
							Banner banner1 = new Banner();
							banner1.setId(banner.getId());
							banner1.setStatus(BannerVO.STATUS_2);
							return banner1;
						}).collect(Collectors.toList());

3. flatMap()

       List<List<Integer>> list = new ArrayList<>();
       List<Integer> list1 = Arrays.asList(1,2,3,4,5);
       List<Integer> list2 = Arrays.asList(6,7,8,9,0);
       list.add(list1);
       list.add(list2);
       Stream<Integer> stream = list.stream().flatMap(integers -> integers.stream().limit(2));
       stream.forEach(System.out::println);
//列印結果
1
2
6
7

注: 與map()不同的是 他會對元素再次降維處理,如果上面是map處理的話會列印出[1,2] [6,7]
這也是所謂的扁平化(最好自己寫個簡單的例子感受一下,並且與map對比一下!!)


4.抽取子流和組合流

1. limit()

		List<String> strList = Arrays.asList("a", "b", "c", "d", "e");
        strList.stream().limit(2).forEach(System.out::println);
//列印結果
a
b

注: limit(long size) 就是把你的當前元素的個數保留多少個(從前往後)比如limit(2)那麼就會保留前兩個元素, 如果流中的元素不夠兩個,那麼保留當前元素


2. skip()

		List<String> strList = Arrays.asList("a", "b", "c", "d", "e");
        strList.stream().skip(2).forEach(System.out::println);
//列印結果
c
d
e

**注:**skip() 與 limit()相反 它是跳過多少元素,保留之後的元素


3. takeWhile()

		Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 0, 1, 2);
        integerStream.takeWhile(integer -> integer < 3).forEach(System.out::println);
 //列印結果
 1
 2

注: 引數是一個斷言,它比較特殊, 從前往後執行,如果迴圈執行到當前元素不符合斷言條件,那麼保留之前的元素, 後面的元素不管符不符合都被捨棄


4. dropWhile()

		Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 0, 1, 2);
        integerStream.dropWhile(integer -> integer < 4).forEach(System.out::println);
//列印結果
 4
 5
 0
 1
 2

注: 這和takeWhile()完全相反 它是從前往後比較時,如果元素符合條件,則把元素丟棄,直到不符合的元素時,保留不符合元素以及之後的所有元素


5. concat()

		Stream<Integer> integerStream1 = Stream.of(1, 2, 3, 4, 5);
        Stream<Integer> integerStream2 = Stream.of(6, 7, 8, 9, 10);
        Stream.concat(integerStream1, integerStream2).forEach(System.out::println);
//列印結果
1
2
3
4
5
6
7
8
9
10

注: 將兩個流組合在一起 和List中的addAll類似, 不過它是靜態方法


5.其他流的轉換

1. distinct()

		Stream<Integer> integerStream1 = Stream.of(1, 2, 2, 1, 1);
        integerStream1.distinct().forEach(System.out::println);
//列印結果
1
2

**注:**和它的名稱一樣, 去重, 去除重複元素,順序不變


2. sorted()

		//按照字串的長度進行排序
		Stream<String> integerStream1 = Stream.of("a", "aaa", "aaaaaaa", "aaaa", "aa");
        integerStream1.sorted(Comparator.comparing(String::length)).forEach(System.out::println);
//列印結果
a
aa
aaa
aaaa
aaaaaaa

注: 其他比較還有Comparator.comparingInt(),Comparator.comparingDouble(),Comparator.comparingLong()都可以進行比較


3. peek()

屬於中間操作,它的作用主要用於除錯,不介紹


6.簡單約減(終結操作)

1. max()

		Stream<Integer> integerStream1 = Stream.of(1, 2, 3, 4, 5);
        Integer integer = integerStream1.max(Integer::compareTo).get();
        System.out.println(integer);
//列印結果
5

注: max()本身返回的是Optional型別,它會返回一個按照比較方式最大的元素


2. min()

與max()同理


3. findFirst()

		Stream<Integer> integerStream1 = Stream.of(1, 2, 3, 4, 5, 4, 3, 2);
        Optional<Integer> first = integerStream1.findFirst();
        System.out.println(first.get());

注: 返回的是返回的是Optional型別 他會尋找第一個元素並返回 通常與limit或者filter使用


4. findAny()

同上述 它是找所有 主要是為了返回Optional型別
注: 和findFirst()同樣 如果上述為空 則返回空的Optional物件 這也是偉大之處 避免了空指標


5. anyMatch()

		Stream<Integer> integerStream1 = Stream.of(1, 2, 3, 4, 5, 4, 3, 2);
        boolean b = integerStream1.anyMatch(integer -> integer > 10);
        System.out.println(b);
//列印結果
false

注: 是否存在匹配 也就是隻要有一個元素匹配上了,就返回true,否則false


6. allMatch()

所有元素都匹配返回true


7. noneMatch()

所有元素都不匹配返回true


7.Optional型別

1.獲取Optional值

1.orElse()

		Optional<Integer> optional = Optional.empty();
        Integer integer = optional.orElse(5);
        System.out.println(integer);
//列印結果
5

注: 當optional為空時 會返回你給的值, 如果不為空,則返回optional包裝的值


2.orElseGet()

	Optional<Integer> optional = Optional.empty();
        Integer integer = optional.orElseGet(this::supplier);
        System.out.println(integer);

    private Integer supplier() {
        return 20;
    }
//列印結果
20

注: 與orElse()相比較當optional為空時 會返回你產生呼叫的結果, 如果不為空,則返回optional包裝的值


3.orElseThrow()

與上述一樣, 只是返回一個異常


2.消費Optional值

1.ifPresent()

		List<Integer> list = new ArrayList<>();
        Optional<Integer> optional = Optional.of(1);
        optional.ifPresent(list::add);
        for (Integer integer : list) {
            System.out.println(integer);
        }
//列印結果
1       

注: 如果該值存在的情況下執行具體的操作


2.ifPresentOrElse()

		List<Integer> list = new ArrayList<>();
       Optional<Integer> optional = Optional.empty();
       optional.ifPresentOrElse(list::add, () ->System.out.println("sssssss"));
        for (Integer integer : list) {
            System.out.println(integer);
        }
//列印結果
sssssss    

注: 如果該值存在的情況下執行具體的操作, 否則 執行另一種操作


3.管道化Optional值

1.map()

		Optional<Integer> optional = Optional.of(1);
        Optional<Integer> result = optional.map(integer -> integer + 1);
        System.out.println(result.get());
//列印結果
2 

注: 對Optional包裝的物件進行操作並返回,和Stream的map類似,只不過Optional的長度是1或0
且如果為空,什麼也不發生,不用擔心null 這也是Optional的優勢之一


2.filter()

且如果為空,什麼也不發生,不用擔心null 這也是Optional的優勢之一
和Stream的map類似,只不過Optional的長度是1或0
且如果為空,什麼也不發生,


3.or()

 		Optional<List<Integer>> optional = Optional.empty();
        Optional<List<Integer>> result = optional.or(this::supplier);
        result.get().forEach(System.out::println);


    private Optional<List<Integer>> supplier() {
        return Optional.of(List.of(1,2,3));
    }
//列印結果
1
2
3

注: 如果Optional是空 那麼會提供一個Optional


4.注意事項

取值時常用的是get() 但是get方法當Optional為空時,會丟擲異常,相當於orElseThrow()丟擲指定的NoSuchElementException異常,所以在用Optional時可以用isPresent()先去判斷,當然,如果在之前先判斷好value的值不為null更方便

1.get()

獲取被包裝的值,上面的map()方法的例子已經用到


2.isPresent()

		Optional<List<Integer>> optional1 = Optional.empty();
        System.out.println(optional1.isPresent());
        Optional<List<Integer>> optional2 = Optional.of(List.of(1,2,3));
        System.out.println(optional2.isPresent());
//列印結果
false
true

注: 如果Optional是空 返回 false, 反之,true, 在我寫這個文章時用的是jdk11,出現了isEmpty()效果是一樣的


5,建立Optional值

有三種方式

1.of()

2.ofNullable()

3.empty()

注: 第一種和第二種時產生一個給定值的Optional,如果value為null,第一個會拋異常,第二個會產生一個空的Optional
第三種是產生一個空的Optional


6.用flatMap構建Optional值的函式

1.flatMap()

	Optional<Double> optional = Optional.of(4d);
    //比較map與flatMap的區別
    Optional<Double> optional1 = optional.flatMap(this::squ);
    Optional<Optional<Double>> optional2 = optional.map(this::squ);
    
    System.out.println(optional1.get());

    private Optional<Double> squ(double x) {
        return x < 0 ? Optional.empty() : Optional.of(Math.sqrt(x));
    }
//列印結果
2

注: map與flatMap的區別:
map方法中的lambda表示式返回值可以是任意型別,在map函式返回之前會包裝為Optional。
但flatMap方法中的lambda表示式返回值必須是Optionl例項

也就是說 map在執行到把每個結果包裝成一個Optional
flatMap把所有結果平鋪之後包裝成一個Optional

flatMap主要是你可以封裝一個方法 然後呼叫時候方便


7.將Optional轉換為流

1.Stream()

 Optional<List<Integer>> optional = Optional.of(List.of(1,2,3,4));
        Stream<List<Integer>> stream = optional.stream();
        Stream<Integer> stream1 = stream.flatMap(integers -> integers.stream().map(integer -> integer + 1));
        stream1.forEach(System.out::println);
//列印結果
2
3
4
5

注: 上述例子可以說明其實結合flatMap時會非常有用 因為Optional的長度是0/1,那麼對於集合或者物件時候用flatMap扁平化處理之後得到更多的元素


8.收集結果

1.iterator()

獲得迭代器(可以用foreach代替)


2.foreach()/foreachOrdered()

迴圈獲取每個元素,foreachOrdered()實在用並行流時可以讓按照順序輸出元素,例子前面已經有很多


3.toArray()

		List<Integer> list1 = Arrays.asList(1,2,3,4,5);
        Integer[] integers = list1.stream().toArray(Integer[]::new);

注: 如果不傳A[]::new時 將返回Object[]


4.collect(Collectors)

	  Stream<Integer> stream1 = Stream.of(1,2,3,4,5);
      Stream<Integer> stream2 = Stream.of(1,2,3,4,5);
      Stream<Integer> stream3 = Stream.of(1,2,3,4,5);
      Stream<Integer> stream4 = Stream.of(1,2,3,4,5);
      Stream<Integer> stream5 = Stream.of(1,2,3,4,5);
      Stream<String> stream6 = Stream.of("1","2","3","4","5");
      Stream<String> stream7 = Stream.of("1","2","3","4","5");
      Stream<Integer> stream8 = Stream.of(1,2,3,4,5);
      //把流中的元素收集到一個list中
      List<Integer> collect1 = stream1.collect(Collectors.toList());
      //把流中的元素收集到一個只可讀的list中
      List<Integer> collect2 = stream2.collect(Collectors.toUnmodifiableList());
      //把流中的元素收集到一個set中
      Set<Integer> collect3 = stream3.collect(Collectors.toSet());
      //把流中的元素收集到一個只可讀set中
      Set<Integer> collect4 = stream4.collect(Collectors.toUnmodifiableSet());
      //把流中的元素收集到一個指定型別的集合中
      List<Integer> collect5 = stream5.collect(Collectors.toCollection(ArrayList::new));
      //對於String型別的可以把元素按照指定的標識分隔開並扁平化成一個字串
      String collect6 = stream6.collect(Collectors.joining(","));
      //對於String型別的可以把元素按照指定的標識分隔開並扁平化成一個字串,並且有指定的前字尾,預設前字尾為空
      String collect7 = stream7.collect(Collectors.joining(",", "", ""));
      //產生(Int|Long|Double)SummaryStatistics物件的收集器,
        //對應的有getCount():獲取元素個數
        //getSum():獲取總和
        //getAverage():獲取元素的平均值
        //getMax()/getMin()獲取最大最小值
      long count = stream8.collect(Collectors.summarizingInt(Integer::intValue)).getCount();

注: 上述是最基本的收集結果


收集到對映表中

1.Collectors.toMap()

        List<User> users = new ArrayList<>();
        for (int i = 0; i < 10; i ++) {
            User user = new User();
            user.setId(i);
            if(i < 3) {
                user.setAccount("ab" + i);
            } else if(i > 3 && i < 7) {
                user.setAccount("cd" + i);
            }else {
                user.setAccount("ef" + i);
            }
            users.add(user);
        }
        Map<Integer, String> collect = users.stream()
                .collect(Collectors.toMap(User::getId, User::getAccount));
        collect.forEach((id, account) -> {
            System.out.println("id=" + id + "  ;account=" + account );
        });
//列印結果
id=0  ;account=ab0
id=1  ;account=ab1
id=2  ;account=ab2
id=3  ;account=ef3
id=4  ;account=cd4
id=5  ;account=cd5
id=6  ;account=cd6
id=7  ;account=ef7
id=8  ;account=ef8
id=9  ;account=ef9

注: 1. 其實就是把物件收集程key,value形式,這個key value都是從每個元素中獲得
如果value是當前的物件 那麼 toMap(key, Function.identity())
2. 存在這種情況, key出現相同,此時會丟擲異常
你可以通過第三個引數來解決,是取新值還是保留之前的值
collect(Collectors.toMap(User::getId, User::getAccount,(oldValue, newValue) -> newValue)) 即可
也存在第四個引數, 指定Map的型別


群組和分割槽

通過上述說的轉化成Map, 這個是按照key相同的分成一組

1.Collectors.groupingBy()

        List<User> users = new ArrayList<>();
        for (int i = 0; i < 10; i ++) {
            User user = new User();
            user.setId(i);
            if(i < 3) {
                user.setAccount("ab");
            } else if(i > 3 && i < 7) {
                user.setAccount("cd" );
            }else {
                user.setAccount("ef");
            }
            users.add(user);
        }
        Map<String, List<User>> collect = users.stream().collect(Collectors.groupingBy(User::getAccount, Collectors.toList()));
        collect.forEach((account, userList) -> {
            System.out.println("account=" + account);
            userList.forEach(user -> System.out.println("id:" + user.getId() + ";account:" + user.getAccount()));
        });
//列印結果
account=cd
id:4;account:cd
id:5;account:cd
id:6;account:cd
account=ef
id:3;account:ef
id:7;account:ef
id:8;account:ef
id:9;account:ef
account=ab
id:0;account:ab
id:1;account:ab
id:2;account:ab

注: 可以看到是按照給定的key把物件分組


2.Collectors.partitioningBy()

        List<User> users = new ArrayList<>();
        for (int i = 0; i < 10; i ++) {
            User user = new User();
            user.setId(i);
            if(i < 3) {
                user.setAccount("ab");
            } else if(i > 3 && i < 7) {
                user.setAccount("cd" );
            }else {
                user.setAccount("ef");
            }
            users.add(user);
        }
        Map<Boolean, List<User>> collect = users.stream().collect(Collectors.partitioningBy(user -> user.getId() == 1));
        collect.forEach((booleanValue, userList) -> {
            System.out.println("booleanValue=" + booleanValue);
            userList.forEach(user -> System.out.println("id:" + user.getId() + ";account:" + user.getAccount()));
        });
//列印結果
booleanValue=false
id:0;account:ab
id:2;account:ab
id:3;account:ef
id:4;account:cd
id:5;account:cd
id:6;account:cd
id:7;account:ef
id:8;account:ef
id:9;account:ef
booleanValue=true
id:1;account:ab

注: 是按照給定條件分成 true和false兩組,用於判斷時特別方便,不用去迴圈了


11.下游收集器

就是對分組的結果 再進行處理 除了上面敘述的 Collectors.toList()等,還有以下收集

1. Collectors.counting()

        List<User> users = new ArrayList<>();
        for (int i = 0; i < 10; i ++) {
            User user = new User();
            user.setId(i);
            if(i < 3) {
                user.setAccount("ab");
            } else if(i > 3 && i < 7) {
                user.setAccount("cd" );
            }else {
                user.setAccount("ef");
            }
            users.add(user);
        }
        Map<String, Long> collect = users.stream().collect(Collectors.groupingBy(User::getAccount, Collectors.counting()));
        collect.forEach((account, count) -> {
            System.out.println("account=" + account + "| count:" + count);
        });
//列印結果
account=cd| count:3
account=ef| count:4
account=ab| count:3

注: 按照key分組完之後, 收集對應的個數


2. Collectors.summing()

        List<User> users = new ArrayList<>();
        for (int i = 0; i < 10; i ++) {
            User user = new User();
            user.setId(i);
            if(i < 3) {
                user.setAccount("ab");
            } else if(i > 3 && i < 7) {
                user.setAccount("cd" );
            }else {
                user.setAccount("ef");
            }
            users.add(user);
        }
        Map<String, Integer> collect = users.stream().collect(Collectors.groupingBy(User::getAccount, Collectors.summingInt(User::getId)));
        collect.forEach((account, count) -> {
            System.out.println("account=" + account + "| count:" + count);
        });
//列印結果
account=cd| count:15
account=ef| count:27
account=ab| count:3

注: 按照key分組完之後, 對收集的結果中的每個組中的id進行求和得出結果作為value值


3. Collectors.maxBy()/minBy()

        List<User> users = new ArrayList<>();
        for (int i = 0; i < 10; i ++) {
            User user = new User();
            user.setId(i);
            if(i < 3) {
                user.setAccount("ab");
            } else if(i > 3 && i < 7) {
                user.setAccount("cd" );
            }else {
                user.setAccount("ef");
            }
            users.add(user);
        }
        Map<String, Optional<User>> collect = users.stream()
                .collect(Collectors.groupingBy(User::getAccount, Collectors.maxBy(Comparator.comparingInt(User::getId))));
        collect.forEach((account, optional) -> {
            System.out.println("account=" + account + "| id:" + optional.get().getId() );
        });
//列印結果
account=cd| id:6
account=ef| id:9
account=ab| id:2

注: 按照key分組完之後, 對收集的結果中的每個組找到id值最大的user物件幷包裝成Optional最為value值 如果存在並列相等的,則只會保留一個物件


3. Collectors.collectingAndThen()

        List<User> users = new ArrayList<>();
        for (int i = 0; i < 10; i ++) {
            User user = new User();
            user.setId(1);
            if(i < 3) {
                user.setAccount("ab");
            } else if(i > 3 && i < 7) {
                user.setAccount("cd" );
            }else {
                user.setAccount("ef");
            }
            users.add(user);
        }
        Map<String, Integer> collect = users.stream()
                .collect(Collectors.groupingBy(User::getAccount, Collectors.collectingAndThen(Collectors.toList(), List::size)));
        collect.forEach((account, size) -> {
            System.out.println("account=" + account + "| size:" +size );
        });
//列印結果
account=cd| size:3
account=ef| size:4
account=ab| size:3

注: 按照key分組完之後, 對收集的結果中再進行一波操作,然後收集到一個集中


3. Collectors.mapping()

        List<User> users = new ArrayList<>();
        for (int i = 0; i < 10; i ++) {
            User user = new User();
            user.setId(i);
            if(i < 3) {
                user.setAccount("ab");
            } else if(i > 3 && i < 7) {
                user.setAccount("cd" );
            }else {
                user.setAccount("ef");
            }
            users.add(user);
        }
        Map<String, List<Integer>> collect = users.stream()
                .collect(Collectors.groupingBy(User::getAccount, Collectors.mapping(Key::getId, Collectors.toList())));
        collect.forEach((account, size) -> {
            System.out.println("account=" + account + "| size:" +size );
        });
//列印結果
account=cd| size:[4, 5, 6]
account=ef| size:[3, 7, 8, 9]
account=ab| size:[0, 1, 2]

注: 與collectingAndThen相反 按照key分組完之後, 對對每個元素進行操作,然後收集到一個集中


4. 其他

  1. Collectors.flatMapping()//如果收集的元素是流可以鋪平
  2. Collectors.summarizingInt() summarizing系列 返回的是該系列物件
  3. filtering() 對於每個元素進行過濾,然後收集起來
    和上述的例子相同,不一一展示!

約簡操作

1.reduce()

		Stream<Integer> stream1 = Stream.of(1,2,3,4,5);
        Optional<Integer> reduce = stream1.reduce((a, b) -> a + b);
        //Optional<Integer> reduce = stream1.reduce(Integer::sum);
        System.out.println(reduce.get());
//列印結果
15

注: 簡單的形式是接受一個二元函式,並從前兩個元素開始持續應用它,得到結果
你也可以給一個初始的元素, 如果流為空,就返回這個元素,就不許需要處理Optional類了
reduce(0, (a, b) -> a + b)
也可以用三個的引數,一般用於處理某個物件屬性時

		Stream<Integer> stream1 = Stream.of(1,2,3,4,5);
        Integer reduce = stream1.reduce(0, Integer::sum, Integer::sum);
        System.out.println(reduce);
//列印結果
15

13.基本型別流

它是解決基本型別到包裝基本型別物件的低效性,可以看成特殊的Stream,所有它的建立和Stream一樣

其他的Api和Stream一樣

1.IntStream

對於short,byte,char boolean int可以使用

1.range()/rangeClosed()

		IntStream stream1 = IntStream.range(0,5);
        stream1.forEach(System.out::println);
//列印結果
0
1
2
3
4

注: 相對於Stream裡的generate和iterate方法 它是生成間隔為1的整數範圍的元素
rangeClosed()是上線包括 [0,5]
range()是[0, 5)


2.boxed()

產生當前流中的元素的包裝器物件流 IntStream -> Stream<Integer>


相關文章