0
点赞
收藏
分享

微信扫一扫

Java Stream流基本使用

郝春妮 2023-07-16 阅读 74

Java Stream流基本使用

1. Stream简介

Stream是Java8中对集合数据操作的一种新的抽象。Stream不是集合元素本身,它只是对数据源(集合、数组等)进行的操作(过滤、映射、排序等)。这些操作会产生另外一个Stream作进一步操作,最后生成一个结果。Stream操作是非破坏性的,它会总产生新的数据集。

2. 获取Stream

可以从Collection、数组或I/O资源中获取Stream:

  • collection.stream():获取Collection流
  • Arrays.stream(array):获取数组流
  • BufferedReader.lines():获取文本流 例如:
List<Integer> list = Arrays.asList(1, 2, 3);
Stream<Integer> stream = list.stream();

int[] arr = new int[]{1, 2, 3}; 
IntStream intStream = Arrays.stream(arr);

3. 中间操作

中间操作返回一个新的Stream,可以有多个。它们只是一种标记,只有在终止操作时才会真正执行。常用的中间操作有:

  • filter:过滤元素
  • map:映射元素
  • flatMap:将流中的每个元素替换为另一个流,然后合并这些流
  • distinct:去除重复元素
  • sorted:排序流中的元素
  • limit:截取流中的元素
  • skip:跳过流中的前N个元素 等等。

4. 终止操作

终止操作会产生结果或副作用,之后Stream管道被关闭。常用的终止操作有:

  • forEach:遍历每个元素
  • count:计算流中元素的总数
  • collect:收集流中的元素到一个Collection中
  • reduce:将流中的元素组合起来
  • min/max:获取流中元素的最小值/最大值
  • anyMatch:检查是否至少匹配一个元素
  • allMatch:检查是否匹配所有元素
  • noneMatch:检查是否没有匹配的元素
  • findFirst:返回第一个元素
  • findAny:返回当前流中的任意元素 等等。

5. 流的消耗

在连续调用中间操作和终止操作之后,Stream会被消耗,不能再被操作。 有几种情况会导致Stream被消耗:

  • 调用一个终止操作
  • 重复调用同一个Stream上的终止操作
  • 在中间操作过程中抛出异常 所以我们要避免重复消耗Stream,导致程序出错。

6. 无限流

可以使用静态方法Stream.iterate()Stream.generate()创建无限流。使用时需要手动限制流大小,否则会导致OutOfMemoryError。 例如:

Stream.iterate(0, n -> n + 2).limit(10).forEach(System.out::println);

Stream.generate(Math::random).limit(5).forEach(System.out::println); 

7. 数字流

使用IntStream、LongStream和DoubleStream可以专门操作基本数值类型的流。它们分别以int、long和double作为操作元素。 可以从boxed数值Stream获取,也可以直接从原始类型数组获取:

IntStream.of(arr).min();
IntStream intStream = Arrays.stream(arr);

8. 再次获取Stream

如果想再次操作同一个流,可以使用Iterator接口中的一个非遍历方法来再次获取,例如:

  • iterator().stream()
  • spliterator().stream() 例如:
Stream<String> stream = list.stream();
stream.filter(s -> s.length() > 5);    //中间操作

Stream<String> stream2 = stream.iterator().stream(); //再次获取流 
stream2.forEach(System.out::println);   //终止操作

9. 串联Stream

可以使用flatMap()方法将一个流中的每个值都换成另一个流,然后把所有流连接起来成为一个流:

Stream<List<Integer>> listStream = Stream.of(  
  Arrays.asList(1, 2),
  Arrays.asList(3, 4)  
);
Stream<Integer> intStream = listStream.flatMap(list -> list.stream());
//intStream流中包含的数据为[1, 2, 3, 4]。

10. 并行Stream

可以调用parallelStream()方法将一个顺序流转为并行流,以利用多核CPU的优势加快处理速度。例如:

list.parallelStream().forEach(System.out::println);

11. 串行化Stream

可以调用sequential()方法将一个并行流转为顺序流。例如:

list.parallelStream().sequential().forEach(System.out::println); 

12. Optional

Stream中的某些方法会返回Optional<T>类型的结果,它代表了可能存在或不存在的值。可以使用isPresent()检查值是否存在,并使用get()获取值,或使用orElseGet()给出默认值。 例如:

Optional<Integer> opt = list.stream().findAny();
if(opt.isPresent()) {
   Integer n = opt.get();  
   System.out.println(n); 
} else {
   Integer n = opt.orElseGet(() -> -1); 
   System.out.println(n);  
}

13. 收集器

Stream提供了Collectors工具类来实现最常见的收集任务。它包含了常见的收集器,可以用于流的collect操作,将流元素收集到一个新的集合中。 常用的收集器有:

  • toList:收集到List
  • toSet:收集到Set
  • toMap:收集到Map
  • joining:连接成字符串
  • summingInt/averagingInt:计算整数总和/平均值
  • reducing:合并流中的元素到一个值 等等。

14. 可选元素

Stream可以处理可选元素,使用Optional类封装 Potential Null值。 这可以避免NullPointerException产生。 Stream上的 Optional相关方法主要有:

  • findFirst:返回第一个元素的Optional
  • max/min:返回最大/最小元素的Optional
  • reduce:可以组合两个 Optional 等等。

Stream API可以有效简化集合数据的操作,让代码变得更加清晰和简洁。理解Stream的各个概念和方法可以让我们运用自如,解决许多日常开发中的数据处理任务。 希望这篇文章能帮助大家基本入门Stream的用法。

举报

相关推荐

java中Stream流的使用

Stream流使用

Stream流(Java)

Java | Stream流

Java Stream流

Stream流的基本操作补充

0 条评论