☝☝☝☝☝☝☝☝☝☝☝☝☝☝☝☝
在JAVA中,涉及到对 数组
、 Collection
等集合类中的元素进行操作的时候,通常会通过 循环的方式 进行逐个处理,或者 使用Stream 的方式进行处理。
例如,现在有这么一个需求:
从给定句子中返回单词长度大于5的单词列表,按长度倒序输出,最多返回3个
在 JAVA7及之前 的代码中,我们会可以照如下的方式进行实现:
/** * 【常规方式】 * 从给定句子中返回单词长度大于5的单词列表,按长度倒序输出,最多返回3个 * * @param sentence 给定的句子,约定非空,且单词之间仅由一个空格分隔 * @return 倒序输出符合条件的单词列表 */ public List<String> sortGetTop3LongWords(@NotNull 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; }
在 JAVA8及之后 的版本中,借助Stream流,我们可以更加优雅的写出如下代码:
/** * 【Stream方式】 * 从给定句子中返回单词长度大于5的单词列表,按长度倒序输出,最多返回3个 * * @param sentence 给定的句子,约定非空,且单词之间仅由一个空格分隔 * @return 倒序输出符合条件的单词列表 */ public List<String> sortGetTop3LongWordsByStream(@NotNull String sentence) { return Arrays.stream(sentence.split(" ")) .filter(word -> word.length() > 5) .sorted((o1, o2) -> o2.length() - o1.length()) .limit(3) .collect(Collectors.toList()); }
直观感受上, Stream
的实现方式代码更加简洁、一气呵成。很多的同学在代码中也经常使用Stream流,但是对Stream流的认知往往也是仅限于会一些简单的 filter
、 map
、 collect
等操作,但JAVA的Stream可以适用的场景与能力远不止这些。
那么问题来了: Stream相较于传统的foreach的方式处理stream,到底有啥优势 ?
这里我们可以先搁置这个问题,先整体全面的了解下Stream,然后再来讨论下这个问题。
笔者结合在团队中多年的代码检视遇到的情况,结合平时项目编码实践经验,对 Stream的核心要点与易混淆用法 、 典型使用场景 等进行了详细的梳理总结,希望可以帮助大家对Stream有个更全面的认知,也可以更加高效的应用到项目开发中去。
Stream初相识
概括讲,可以将Stream流操作分为 3种类型 :
- 创建Stream
- Stream中间处理
- 终止Steam
每个Stream管道操作类型都包含若干API方法,先列举下各个API方法的功能介绍。
- 开始管道
主要负责新建一个Stream流,或者基于现有的数组、List、Set、Map等集合类型对象创建出新的Stream流。
API | 功能说明 |
---|---|
stream() | 创建出一个新的stream串行流对象 |
parallelStream() | 创建出一个可并行执行的stream流对象 |
Stream.of() | 通过给定的一系列元素创建一个新的Stream串行流对象 |
- 中间管道
负责对Stream进行处理操作,并返回一个新的Stream对象,中间管道操作可以进行 叠加 。
API | 功能说明 |
---|---|
filter() | 按照条件过滤符合要求的元素, 返回新的stream流 |
map() | 将已有元素转换为另一个对象 |