前言

Java8的特性Stream流,专门用于对一组数据进行处理的api,在日常开发中,使用比较普遍,但是在我们体验到Stream带来的便利的同时,也需要注意一些建议和风险。

更多关于Java8的特性介绍,可以查看另一篇文章>

Stream体验

Stream目前被开发中所青睐的原因有如下几点:

1、Stream api可以进行链式调用,使用起来比较方便,同时增加了简洁性;

例如:collection.stream().filter(...).map(...).sorted(...)

2、Stream可以对数据集进行一系列的中间处理,而且支持多种操作如过滤、映射、归约等,提高了数据处理的灵活性;

3、和Lambda表达式、函数式接口、方法引用等结合使用,进一步提高代码简洁性。

例如:映射 .map(String::toLowerCase)

建议与风险

在使用时,需要关注一些坑点:

1、使用链式调用时注意适当换行,避免单行过长,降低了代码的可读性,可以考虑:每一个操作进行换行、逻辑分组进行换行、复杂参数与逻辑进行换行等。

例如:

list.stream()
    .filter(e -> e.getSomeProperty().equals("value") && e.isSomeCondition())
    .map(e -> new ComplexObject(e))
    .collect(...);

2、Stream中并行流api parallel()可以借助多核提高数据处理速度,但是要注意并行流处理有中间状态的操作时,如排序,可能会产生非预期结果。

例如:

// sorted排序,但因为使用parallel()结果并不能保证顺序性
List<Integer> list = ...;
list.stream().parallel()
    .filter(x -> x > 1).sorted();

3、Stream提供的api中,对于中间操作的api,如filter、map、peek等,如果不进行最终的结束操作如forEach、reduce、collect等,会导致中间操作不执行。

例如:

// 使用中间操作打印原始字符串,并不会被执行;此处应该使用结束操作forEach
List<String> strings = ...
strings.stream()
 			.peek(s -> System.out.println("original: " + s)) 

4、最后就是避免滥用,考虑是否有必要在单个方法中对同一个数据集多次Stream操作以得到不同的数据集,也许此时使用最基本的for来统一进行数据的预处理可能更合适。

总结

Stream API是Java 8中一个强大而灵活的特性,可以极大地提升代码的简洁性和效率。但我们在使用时应注意其使用建议和潜在风险,避免陷入常见的坑点。合理使用Stream API能够在确保代码可读性和维护性的同时,提高开发效率。