51

【Java必修课】图说Stream中的skip()和limit()方法及组合使用

 4 years ago
source link: http://www.cnblogs.com/larrydpk/p/12078124.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

1 简介

本文将讲解Java 8 Stream中的两个方法: skip()limit() 。这两个方法是 Stream 很常用的,不仅各自会被高频使用,还可以组合出现,并能实现一些小功能,如 subList 和分页等。

2 skip()方法

见名知义, skip() 方法用于跳过前面n个元素,然后再返回新的流,如图所示:

EZBVvma.png!web

来看看代码:

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个元素,返回新的流,如图所示:

mYNFbyJ.png!web

代码如下:

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() 会有性能问题。

欢迎关注公众号< 南瓜慢说 >,将持续为你更新...

JNra2eQ.jpg!web

欢迎加博主微信,做一个点赞之友,哈哈...

FNb2eiQ.jpg!web

多读书,多分享;多写作,多整理。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK