什么是 Java Stream API?

作为一款强大的函数式编程工具,Java 8 引入了 Stream API,使得 Java 集合操作变得更加灵活和高效。本文将为您介绍 Java Stream API 的概念和用法,并提供一些实例来帮助您更好地理解。

什么是 Java Stream API?

Java Stream API 是一种函数式编程风格的迭代器,它可以让我们以声明式的方式对集合进行操作。相比传统的 for 循环和迭代器,Stream API 更加灵活、易于并行化和优化,可以让我们更加方便地对数据进行处理。

Stream API 的核心概念包括:

  • 流(Stream):表示数据流,是一系列支持函数式操作的元素集合。
  • 操作(Operation):可以对数据流进行的操作,比如过滤、映射、排序、聚合等。
  • 惰性求值(Lazy Evaluation):操作在调用终端操作(Terminal Operation)之前不会被执行,这使得我们可以在处理大数据集合时更加高效。

Stream API 的基本用法

在开始使用 Stream API 之前,需要将一个集合或数组转换为一个流。可以通过调用 stream() 方法或 parallelStream() 方法来获取一个流,其中 stream() 方法是顺序流,parallelStream() 方法是并行流。

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream = list.stream(); // 获取顺序流
Stream<Integer> parallelStream = list.parallelStream(); // 获取并行流

在获取到流之后,我们可以使用 Stream API 提供的一系列操作来对数据进行处理。这些操作可以分为两类:

  • 中间操作(Intermediate Operation):包括过滤、映射、排序、去重、限制等操作,返回的仍然是一个流。
  • 终端操作(Terminal Operation):包括 forEach、count、collect、reduce 等操作,返回的是一个非流类型的结果。

下面是一些常见的操作实例:

过滤操作

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> result = list.stream()
    .filter(i -> i % 2 == 0)
    .collect(Collectors.toList()); // 过滤出偶数,返回 [2, 4]

映射操作

List<String> list = Arrays.asList("apple", "banana", "orange");
List<Integer> result = list.stream()
    .map(String::length)
    .collect(Collectors.toList()); // 映射出每个字符串的长度,返回 [5, 6, 6]

排序操作

List<Integer> list = Arrays.asList(3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5); 
List<Integer> result = list.stream()
     .distinct() 
    .sorted() 
    .collect(Collectors.toList()); // 去重并排序,返回 [1, 2, 3, 4, 5, 6, 9]

限制操作

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> result = list.stream()
    .limit(3)
    .collect(Collectors.toList()); // 取前三个元素,返回 [1, 2, 3]

统计操作

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
long count = list.stream().count(); // 计算元素数量,返回 5
int max = list.stream().max(Integer::compareTo).orElse(0); // 计算最大值,返回 5
int min = list.stream().min(Integer::compareTo).orElse(0); // 计算最小值,返回 1
int sum = list.stream().mapToInt(Integer::intValue).sum(); // 计算元素总和,返回 15
double average = list.stream().mapToInt(Integer::intValue).average().orElse(0); // 计算平均值,返回 3.0

Stream API 的并行化

Java 8 中的 Stream API 可以实现并行处理数据,提高数据处理效率。可以通过调用 parallelStream() 方法来获取一个并行流,这样 Stream API 就会在多个线程上同时处理数据。相比顺序流,使用并行流可以在处理大数据集合时获得更快的处理速度。

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
int result = list.parallelStream()
    .mapToInt(Integer::intValue)
    .sum(); // 并行计算元素总和,返回 15

使用案例:

  1. 计算数组的平均值

    int[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    
    double average = Arrays.stream(nums)
                           .parallel()
                           .average()
                           .getAsDouble();
    
    System.out.println("Average: " + average);
    
  2. 过滤集合中的元素

    List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Edward", "Frank");
    
    List<String> filteredNames = names.parallelStream()
                                      .filter(name -> name.length() > 4)
                                      .collect(Collectors.toList());
    
    System.out.println("Filtered names: " + filteredNames);
    
  3. 使用自定义函数进行映射

    List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5);
    
    List<Integer> mappedNums = nums.parallelStream()
                                   .map(num -> num * num)
                                   .collect(Collectors.toList());
    
    System.out.println("Mapped nums: " + mappedNums);
    
  4. 对数组进行排序

    int[] nums = {10, 5, 8, 3, 6, 2, 7, 1, 9, 4};
    
    int[] sortedNums = Arrays.stream(nums)
                             .parallel()
                             .sorted()
                             .toArray();
    
    System.out.println("Sorted nums: " + Arrays.toString(sortedNums));
    
  5. 计算字符串中某个字符的出现次数

    String str = "Hello, world!";
    
    long count = str.chars()
                   .parallel()
                   .filter(ch -> ch == 'l')
                   .count();
    
    System.out.println("Number of 'l's in the string: " + count);
    
    
  6. 对集合中的元素进行去重

    List<Integer> nums = Arrays.asList(1, 2, 3, 2, 4, 5, 3, 6, 7, 1);
    
    List<Integer> distinctNums = nums.parallelStream()
                                      .distinct()
                                      .collect(Collectors.toList());
    
    System.out.println("Distinct nums: " + distinctNums);
    
    
  7. 将字符串列表转换为大写并拼接成一个字符串

    List<String> words = Arrays.asList("hello", "world", "java", "stream");
    
    String result = words.parallelStream()
                         .map(String::toUpperCase)
                         .collect(Collectors.joining(", "));
    
    System.out.println("Result: " + result);
    
  8. 对集合进行分组并统计每组的数量

    List<String> words = Arrays.asList("apple", "banana", "cherry", "date", "elderberry", "fig");
    
    Map<Character, Long> wordCountMap = words.parallelStream()
                                              .collect(Collectors.groupingByConcurrent(word -> word.charAt(0), Collectors.counting()));
    
    System.out.println("Word count map: " + wordCountMap);
    
  9. 对集合中的元素进行拼接操作

    List<String> words = Arrays.asList("hello", "world", "java", "stream");
    
    String result = words.parallelStream()
                         .reduce("", (s1, s2) -> s1 + s2);
    
    System.out.println("Result: " + result);
    
    
  10. 使用并行流生成斐波那契数列

    int count = 10;
    
    List<Integer> fibonacciSequence = Stream.iterate(new int[]{0, 1}, n -> new int[]{n[1], n[0] + n[1]})
                                             .parallel()
                                             .limit(count)
                                             .map(n -> n[0])
                                             .collect(Collectors.toList());
    
    System.out.println("Fibonacci sequence: " + fibonacciSequence);
    
    

需要注意的是,并行化并不是总能提高性能,特别是在数据量较小、处理时间较短或者程序存在其他瓶颈的情况下,并行化反而可能会降低性能。

总结

Stream API 是 Java 8 中非常重要的一部分,它可以大大简化集合的操作并提高代码的可读性和可维护性。本文介绍了 Stream API 的基本概念和使用方法,并提供了一些常见的操作实例。希望本文能够帮助您更好地理解和使用 Java Stream API。

你可能感兴趣的:(Java高级,java,Stream)