一、Stream简介
stream流是一串连续的元素序列,可以进行各种操作以实现数据的转换和处理,比如:筛选、排序、聚合。
(1) stream流把对流的操作分为两种:
- 中间操作符:中间操作符在执行指定的处理后,数据流依然可以传递到下一级。包含map,limit、filter、skip等
- 终止操作符:终止操作符用来对数据进行收集,数据到了终止操作符后,就不再往下流动,并且终止操作符只能使用一次。包含collect、count、min-max、forEach等
stream的一些特性:
- stream具有延迟执行的特性,只有调用中断操作时,中间操作才会被执行。
- stream提供了并行流的支持,可以将数据分成多个部分进行并行处理,但在得到了数据通常是无序的。
- stream流不会进行数据的存储,而是按照指定规矩进行计算。
二、Stream的创建
1.从集合创建,可以调用集合的stream()方法来创建一个stream对象,如下:
List<Integer> nums = Arrays.aslist(1,2,3,4); Stream<Integer> stream = nums.stream();
2.从数组创建,可以调用Arrays类的stream()方法进行创建,如下:
String[] names = {"a","b"}; Stream<String> stream = Arrays.stream(names);
3.通过Stream.of()创建,可以通过Stream.of()方法进行创建,如下:
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
4.通过 Stream.builder() 创建,当添加的元素个数不确认时,可以使用Stream.builder()创建相应相应的对象,并使用add方法添加元素,如下:
Stream.Builder<String> builder = Stream.builder(); builder.add("A"); builder.add("B"); builder.add("C"); Stream<String> stream = builder.build();
5.通过生成器创建,可以使用Stream.generate()方法和Stream.iterate()方法,如下:
Stream<Integer> stream1 = Stream.iterate(() -> 0).limit(3); // 3个0 Stream<Integer> stream2 = Stream.generate(0,n -> n + 1).limit(3);
三、常见的中间操作符
1.筛选(Filter),filter()方法接受一个函数作为参数,用于过滤Stream中的元素,只有满足函数要求的元素才会被保留,如下:
Stream<Integer> stream = Stream.of(1,2,3,4,5); Stream<Integer> filtered = stream.filter(n -> n % 2 == 0 ) ; // 偶数
2.映射(Map),map()方法接受一个函数作为参数,用于对stream流中的数据进行映射转换,在之后会构成一个新的stream流。
3.扁平映射(FlatMap),与map不同之处在于它先将每个值都换成另一流,然后再将所有流连接成一个流,其主要解决嵌套集合的问题。如下:
Stream<Integer> stream = stream.of(1,2,3,4); Stream<Integer> mapped = stream.map(x -> x + 3); // 每个+3 List<List<Integer>> nestedList = Arrays.asList( Arrays.asList(1, 2), Arrays.asList(3, 4), Arrays.asList(5, 6) ); Stream<Integer> flattenedStream = nestedList.stream().flatMap(List::stream); // 扁平化为一个流
4.聚合(max、min、count),主要用来对数据进行统计,类似于MySQL中的,其中max,min返回的是Optional对象,如下:
Stream<Integer> stream = Stream.of(1,2,3,4,5); Optional<Integer> max1 = stream.max(Integer::compareTo); System.out.println("自然排序的最大值:" + max1.get());
其中Optional对象,主要用于解决空指针异常的问题,Optional类可以是一个null的容器对象,如果值存在则isPresent()返回true,可以调用get()获取该对象。
5.截断操作(limit 和 skip)
- limit(n):保留流中的前n个。
- skip(n):跳过流中的前n个。
如下:
Stream<Integer> stream = Steam.of(1,2,3,4); Stream<Integer> limited = stream.limit(2); Stream<Integer> skipped = steam.skip(2);
四、Stream的终端操作符
1.ForEach,它接受一个Consumer函数作为参数,对流中的每个元素执行该函数。如下:
List<String> names = Arrays.asList("A","b"); names.stream.ForEach(System.out::println);
2.聚合操作(reduce和collect)
- reduce:reduce接受一个BinaryOpreator函数作为参数,对流中的元素进行合并操作,该方法会将流中的第一个元素作为初始值,然后将初始值与下一个元素传递给BinaryOperator函数进行计算,得到的结果再与下一个元素进行计算,以此类推,直到遍历完所有元素。
- collect:collect接受一个Collector接口的实现作为参数,对流中元素进行收集和汇总的操作。例如进行字符串连接、分组等。
如下:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); Optional<Integer> sum = numbers.stream().reduce((a, b) -> a + b); sum.ifPresent(System.out::println); // 输出结果: 15 List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); String joinedNames = names.stream().collect(Collectors.joining(", ")); System.out.println(joinedNames); // 输出结果: Alice, Bob, Charlie