简介

当我们在对数组collection等集合中的元素进行操作的时候一般会使用迭代的方式去逐个处理,为了简化代码,加快开发速度,Java 在 JDK8 版本添加Stream流操作,用来以“做什么而非怎么做”的方式处理集合。

例如,现在有一个需求:

从给定句子中返回单词长度大于 5 的单词列表,并按长度倒序排列,最多返回 3 个

在 JDK7 及以前的版本,我们可以通过以下方式进行实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static List<String> sortGetTop3LongWords(String sentence) {
// 分割句子,得到单词列表
String[] words = sentence.split(" ");
List<String> wordList = new ArrayList<>();
// 迭代判断单词长度,先过滤出长度按要求的单词
for (String word : words) {
if (word.length() > 5)
wordList.add(word);
}
// 按长度倒叙排列长度符合要求的单词
wordList.sort(((o1, o2) -> o2.length() - o1.length()));
// 判读List集合的长度,如果大于3截取前三个数据的子List返回
if (wordList.size() > 3) {
wordList = wordList.subList(0, 3);
}
return wordList;
}

在 JDK8 及以后的版本,我们可以借助 Stream 流,写出更加优雅的代码:

1
2
3
4
5
6
7
public static List<String> sortGetTop3LongWordsByStream(String sentence) {
return Arrays.stream(sentence.split(" ")) // 分割
.filter(word -> word.length() > 5) // 过滤
.sorted(((o1, o2) -> o2.length() - o1.length())) // 排序
.limit(3) // 限制
.collect(Collectors.toList()); // 转List
}

简直是太优雅力 😎

Stream 流操作

概括的讲,Stream 流操作可以分为 3 种类型:

  • Stream 的创建操作
  • Stream 的中间操作
  • Stream 的终止操作

创建操作

数据来源 方法名 说明
单列集合 default Stream stream() Collection 中的默认方法
单列集合 default Stream parallelStream() 返回一个可以并行执行的 Stream 流对象
双列集合 无法直接创建 Stream 流,可以通过 keySet,entrySet 等方法间接创建
数组 static Stream stream(T[] array) Arrays 中的静态方法
零散数据 static Stream of(T… values) Stream 中的静态方法

中间操作

方法名 含义
Stream filter(Predicate<? super T> predicate) 用于通过设置条件过滤出元素
Stream limit(long maxSize) 保留前 n 个元素
Stream skip(long n) 去除前 n 个元素
Stream sorted(Comparator<? super T> comparator) 对流进行排序
Stream distinct() 元素去重(依赖 hashCode 和 equals 方法)
static Stream concat(Stream<? extends T> a, Stream<? extends T> b) 合并两个流
Stream map(Function<? super T, ? extends R> mapper) 转换流中的元素类型

终止操作

方法名 含义
void forEach(Consumer<? super T> action) 遍历
long count() 统计
Object[] toArray() 将流中的元素转换为 Object 类型数组
A[] toArray(IntFunction<A[]> generator) 将流中的元素转换为指定类型的数组
<R, A> R collect(Collector<? super T, A, R> collector) 将流中的元素转换为指定类型的数组