目录
简介
特点
Stream操作步骤
创建
中间操作
筛选与切片
filter(Predicate p)
distinct()
limit(long maxSize)
skip(long n)
映射
map(Function f)
flatMap(Function f)
排序
自然排序
定制排序
终止操作
匹配与查找
归约
收集
好处
不足
简介
在编写代码的过程中,我们经常要对集合或数组数据进行操作,而有了 Stream API,我们能够非常轻松的对集合、数据进行映射、过滤、查找等操作,使得我们能够像操作数据库一样的操作集合。
Stream 本身并不存储元素,它并不改变源数据,每次操作都会形成一个新的流,并且只有执行了Stream的终止操作,中间的过滤、查找等操作才会执行。
集合注重存储,Stream注重计算。集合是基于内存层面的,而Stream是基于CPU的。
特点
高效率的并行操作
多种功能的聚合操作
函数式编程,代码更加简洁,提高编程效率
Stream操作步骤
只有执行了终止操作,中间操作才会执行。这也是 Stream 的延迟执行的体现
创建
1.集合创建流
@Test
public void test() {
List<String> list = new ArrayList<>();
list.add("H");
list.add("E");
list.add("l");
list.add("l");
list.add("O");
Stream<String> stream = list.stream();
}
2.数组创建流
@Test
public void test() {
Integer[] arr = {1,2,3,4,5,6,7,8,9};
Stream<Integer> stream = Arrays.stream(arr);
}
3.使用of方法创建流
@Test
public void test() {
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 6);
}
4.创建无限流
@Test
public void test() {
// iterator
Stream<Integer> iterate = Stream.iterate(0, ele -> ele + 2);
iterate.forEach(System.out::println);
}
中间操作
筛选与切片
filter(Predicate p)
接收断言型函数式接口,对流中的元素进行过滤
distinct()
对流进行去重
limit(long maxSize)
限制流中的元素数量。可以使用 limit方法来终止无限流
skip(long n)
跳过流中的 n 个元素
映射
map(Function f)
接收一个功能型函数式接口的实现类,该函数式接口中的抽象方法会被用到流中的每一个元素上
flatMap(Function f)
flatMap 的功能和 map 类似,都是将方法应用到流中的每个元素上
排序
自然排序
Stream< T > sorted(); 使用自然排序
定制排序
Stream< T > sorted(Comparator<? super T> comparator); 使用定制排序
终止操作
匹配与查找
@Test
public void test() {
List<String> stringList = Arrays.asList("hello","world","hi","word");
boolean b = stringList.stream().allMatch(str -> str.length() > 5);
System.out.println(b); // false
}
归约
reduce 会遍历流中的元素
@Test
public void test() {
List<String> stringList = Arrays.asList("hello","world","hi","word");
String reduce1 = stringList.stream().reduce("", (s1, s2) -> String.valueOf(s1.length() + s2.length()));
System.out.println(reduce1);
List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// Optional 是 Java8 新增的防止空指针的类,通过 get() 方法可以获取到包装的值
Optional<Integer> reduce2 = integerList.stream().reduce((i1, i2) -> {
return i1 + i2;
});
System.out.println(reduce2.get());
// 上述代码等同于下面代码
Optional<Integer> reduce3 = integerList.stream().reduce(Integer::sum);
System.out.println(reduce3.get());
}
收集
收集在开发中也是非常实用的终止操作。常常用来对流进行中间操作最后收集生成集合
Collector 接口中方法的实现决定了如何对流执行收集的操作(如收集到 List、Set、Map)
好处
1.它是java对集合操作的优化,相较于迭代器,使用Stream的速度非常快,并且它支持并行方式处理集合中的数据,默认情况能充分利用cpu的资源。同时支持函数式编程,代码非常简洁。
2.Stream是一种用来计算数据的流,它本身并没有存储数据。你可以认为它是对数据源的一个映射或者视图这让我们使用起来方便简洁.
不足
1.代码难以调试,因为不像for循环那样可以每一行打断点调试了
2.在数据量不是很大的情况下,stream流是没有优势的,也就是说数据量小,且同意业务内多处使用stream处理数据,这时执行耗时比for循环更多,只有业务量达到百万级别才体现出优势。
3.不要重复消费对象、不要修改数据源