Java 8中出现的Stream,可以视为是对集合操作的一种增强,它位于java.util.stream包中。配合lambda使用,可以让我们对集合的操作(如取值、排序、过滤等)变得十分简洁、高效、优雅。
鉴于之前很少使用Java 8的新特性,包括lambda,最近在使用Stream时竟然会感到一丝的愉悦。当然自己对Stream的使用还非常粗浅的,目前基本上把它作为使用for循环或者是foreach处理集合的一种替代品。

下面介绍几种自己常用的常规操作,为了方便,先来定义一个简单的类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class Person {

private String name;

private int age;

Person(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
}

取值

假如有这样一个列表,List<Person> persons,我们想要得到列表中所有人的名字,在Java 8之前,我们会这样做:

1
2
3
4
List<String> names = new ArrayList<>(persons.size());
for (Person person : persons) {
names.add(person.getName());
}

但是如果借助Stream,我们可以用一行代码完成这个操作:

1
List<String> names = persons.stream().map(Person::getName).collect(Collectors.toList());

即在map方法中,指定取值的方法。

排序

再假如要把persons列表中的对象按年龄排序,我们可以利用Stream这样做:

1
2
3
persons.stream()
.sorted(Comparator.comparing(Person::getAge))
.collect(Collectors.toList());

即在sorted中,实现Comparator接口的comparing方法,指定需要排序的字段。

当然这样做看起来更加简单,

1
Collections.sort(persons, Comparator.comparing(Person::getAge));

但是如果要得到排序后的persons列表的名字列表呢,这时候用Stream肯定是最简单的方法之一:

1
2
3
4
persons.stream()
.sorted(Comparator.comparing(Person::getAge))
.map(Person::getName)
.collect(Collectors.toList());

过滤

得到年龄大于20岁的Person的列表,借助Stream

1
2
3
4
persons.stream()
.filter(person -> person.getAge() > 20)
.map(Person::getName)
.collect(Collectors.toList());

即在filter中指定过滤的条件。

组合使用

Stream的一个很爽的特性,就是可以把它提供的API进行组合使用。例如我们要得到排序后的persons列表中年龄大于20岁的所有人的姓名列表:

1
2
3
4
5
List<String> names = persons.stream()
.sorted(Comparator.comparing(Person::getAge))
.filter(person -> person.getAge() > 20)
.map(Person::getName)
.collect(Collectors.toList());

总结

上面提到的几个Stream的用法,都是最基本、最常规的操作,Stream还有很多其它高效、有趣的玩法,比如下面这边文章就介绍的非常详细:

Java 8 中的 Streams API 详解