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() 会有性能问题.
来源: https://www.cnblogs.com/larrydpk/p/12078124.html