文章目录
Java SE8 流
综述
如果我们要迭代的话,一般是进行这样的操作:
ArrayList<Integer> contents = new ArrayList<Integer>(){
{
for(int i = 0; i < 100; i++){
add(i * i);}}};
//foreach迭代,进行计数操作
int count = 0;
for (int s : contents)
if (s % 3 == 0)
count++;
System.out.println("能被3整除的数字有" + count + "个");
在java SE8之后,我们可以这样:
ArrayList<Integer> contents = new ArrayList<Integer>(){
{
for(int i = 0; i < 100; i++){
add(i * i);}}};
//流操作
int count = (int) contents.stream().parallel().mapToInt(s -> s).filter(s -> s % 3 == 0).count();
System.out.println("能被3整除的数字有" + count + "个");
上面代码只是说明了流与for循环的不同,看起来似乎流的逼格更高,但流真正好处体现在哪里?
现在假设我们要设计一个学生管理系统,有一个需求:假设现在年纪里要评选奖学金,我们需要把全年级的学生根据综测排名,然后筛选出时长大于20的人,然后根据奖学金的数量选出人数,根据综测排名我们先分析一下步骤的实现:
- 输入所有学生信息
- 查重,将重复的学生信息删除
- 按绩点排序
- 选出前三个(假设奖学金只有三个)
- 按班分组
可以想象用for循环来实现需要多少代码和逻辑,但是用流操作就很简单
下面是代码实现:
Map<Integer, List<Student>> map = students.stream()
.parallel()
.distinct()
.sorted(Comparator.comparing(Student::getGPA).reversed())
.filter((n) -> n.getVolunteerTime() > 20)
.limit(3)
.collect(Collectors.groupingBy(Student::getClassID));
ps:我们可以发现流的版本比循环的版本更简洁,可读性更高。因为我们不必扫描整个代码去查找过滤和计数操作。方法名就可以直接告诉我们其意欲何为。而且,循环需要非常详细的指定操作的顺序,而流就可以以其想要的任何代码来调度这些操作。
- 流的操作不会修改其数据源,所有的操作都是生成一个新的流
- 流的操作是尽可能的惰性执行,这意味着直至需要其结果时,操作才会执行。
总的来说,流的创建分为三步:
- 创建一个流:
contents.stream()
- 将初始流转换为其他流的中间过程,可能包含很多步骤
- 终止操作。
//还有其他很多终止操作
.count();
第一步 转换流的常用方法
- 将集合转化成流
就像上面的代码,可以使用Connection接口的stream方法将任何集合转换成一个流
ArrayList<Integer> contents =...;
Stream<Integer> stream = contents.stream();
- 将数组转化成流
使用静态的Stream.of()方法:这个方法接受一个数组,当然也支持可变参数,所以我们可以直接传值:
Stream<Integer> stream = Stream.of(1,2,3,4,5,6);
- 创建一个空流
Stream<Integer> stream = Stream.empty();
- 创建一个无限流
- 使用静态方法generate(),下面是这个方法的定义
public static<T> Stream<T> generate(Supplier<T> s)
- 这个方法的参数是一个函数式接口,也就意味着我们可以用lambda表达式, 这段代码会生成一个无限流,流的内容全部都是1。
Stream<Integer> stream = Stream.generate(() -> 1);
- 或者下面这段代码,会生成一个无限随即数的流:
Stream<Double> stream = Stream.generate(Math::random);
- 生成自定义的无限流
使用iterate()方法:
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
第一个参数是种子,第二个参数的lambda表达式会对种子进行不断迭代:
Stream