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()
會有性能問題。
歡迎關注公眾號<南瓜慢說>,將持續為你更新...
歡迎加博主微信,做一個點贊之友,哈哈...
多讀書,多分享;多寫作,多整理。