圖說Stream中的skip()和limit()方法及組合使用


1 簡介

本文將講解Java 8 Stream中的兩個方法:skip()limit()。這兩個方法是Stream很常用的,不僅各自會被高頻使用,還可以組合出現,並能實現一些小功能,如subList和分頁等。

2 skip()方法

見名知義,skip()方法用於跳過前面n個元素,然后再返回新的流,如圖所示:

來看看代碼:

List<Integer> result = Stream.of(1, 2, 3, 4, 5, 6)
  .skip(4)
  .collect(Collectors.toList());
List<Integer> expected = asList(5, 6);
assertEquals(expected, result);

 

方法skip()的參數n的四種情況:

(1)當n<0時,拋IllegalArgumentException異常;

(2)當n=0時,相當沒有跳過任何元素,原封不動、完璧歸趙;

(3)當0<n<length時,跳過n個元素后,返回含有剩下的元素的流;

(4)當n>=length時,跳過所有元素,返回空流。

3 limit()方法

對於limit()方法,它是用於限制流中元素的個數,即取前n個元素,返回新的流,如圖所示:

代碼如下:

List<Integer> result = Stream.of(1, 2, 3, 4, 5, 6)
  .limit(4)
  .collect(Collectors.toList());
List<Integer> expected = asList(1, 2, 3, 4);
assertEquals(expected, result);

 

方法limit()的參數n的四種情況:

(1)當n<0時,拋IllegalArgumentException異常;

(2)當n=0時,不取元素,返回空流;

(3)當0<n<length時,取前n個元素,返回新的流;

(4)當n>=length時,取所有元素,原封不動、完璧歸趙。

4 對無限流的操作

流Stream分為有限流和無限流,前面的例子我們都是使用的有限流,與Java集合類不同,流是可以無限的。對於無限流,skip()limit()表現出了極大的差異,先上代碼:

Stream.iterate(1, i -> i + 1)
  .filter(num -> (num & (num - 1)) == 0)
  .limit(10)
  .forEach(System.out::println);
System.out.println("----------------");
Stream.iterate(1, i -> i + 1)
  .filter(num -> (num & (num - 1)) == 0)
  .skip(10)
  .forEach(System.out::println);

 

執行后發現,limit()是可以將無限流轉化為有限流的,所以我們也可以認為它是一個短路操作。而skip()則不行,不管你跳過了前面多少個元素,總還是會有源源不斷的元素過來,無法收斂。

上述代碼的結果是:

通過limit()輸出了前十個2的n次方值:
1, 2, 4, 8, 16, 32, 64, 128, 256, 512

skip()跳過了前10個,繼續輸出,但會不斷執行下去(會有int的溢出現象):

1024, 2048, 4096, 8192, 16384, 32768...

5 組合應用

除了兩者各自有各自的功能外,我們通過組合使用,可以實現其它功能。

5.1 與subList的替換

集合類如List是有subList()這個方法的,可以截取List中的某一部分,這個功能還可以通過組合skip()limit()使用得到,如下面代碼:

List<Integer> list = asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
List<Integer> expected = list.subList(3, 7);

List<Integer> result = list.stream()
  .skip(3)
  .limit(7 - 3)
  .collect(Collectors.toList());
assertEquals(expected, result);

 

subList(startIndex, endIndex)轉換成skip(startIndex).limit(endIndex - startIndex)

5.2 分頁

可以通過組合使用skip()limit()進行分頁,如下面代碼:

int pageSize = 10;
int pageIndex = 7;

List<Integer> expected = asList(61, 62, 63, 64, 65, 66, 67, 68, 69, 70);
List<Integer> result = Stream.iterate(1, i -> i + 1)
  .skip((pageIndex - 1) * pageSize)
  .limit(pageSize)
  .collect(Collectors.toList());

assertEquals(expected, result);

 

上面代碼例子是獲取了第七頁數據,每頁大小為10。

6 總結

本文介紹了Java 8的Stream接口中兩個常用的方法:skip()limit(),比較簡單易懂,也介紹了怎么組合使用。需要注意的是,如果Stream過大或是無限流,小心skip()會有性能問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM