Java8 - 流式编程

Java8 中的另一大亮点Stream,它于io包中的InputStream和OutputStream是完全不同的概念

Java8中的Stream是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作,或者大批量的数据操作

Java中的流式编程(Stream Programming)是指通过Stream API来对集合(Collection)或数组(Array)进行一系列的操作。Stream API可以将集合或数组中的元素转换成一个流(Stream),通过一些中间操作(Intermediate Operations)来进行筛选、排序、映射等操作,最终通过终止操作(Terminal Operations)来得到结果。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

int sum = numbers.stream()
                .filter(n -> n % 2 == 0)
                .mapToInt(Integer::intValue)
                .sum();

System.out.println("Sum of even numbers: " + sum);

在这个例子中,首先创建了一个包含10个整数的List集合。然后将这个集合转换成一个流(Stream),通过filter操作保留集合中的偶数,通过mapToInt操作将流中的元素转换成int类型,最后通过sum操作将所有元素相加得到结果。

举例

1.筛选集合中的元素

假设有一个包含多个字符串的List集合,需要筛选出所有长度大于等于5的字符串,可以使用流式编程来实现:

List<String> strings = Arrays.asList("apple", "banana", "orange", "pear", "grape");

List<String> filteredStrings = strings.stream()
                                      .filter(s -> s.length() >= 5)
                                      .collect(Collectors.toList());

System.out.println(filteredStrings);
输出结果为:[apple, banana, orange]

2.对集合进行排序

假设有一个包含多个数字的List集合,需要对其中的数字按照从小到大的顺序进行排序,可以使用流式编程来实现:

List<Integer> numbers = Arrays.asList(5, 1, 8, 3, 2, 7);

List<Integer> sortedNumbers = numbers.stream()
                                      .sorted()
                                      .collect(Collectors.toList());

System.out.println(sortedNumbers);
输出结果为:[1, 2, 3, 5, 7, 8]

3.计算集合中的元素的平均值

假设有一个包含多个数字的List集合,需要计算其中的数字的平均值,可以使用流式编程来实现:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

double average = numbers.stream()
                        .mapToInt(Integer::intValue)
                        .average()
                        .orElse(0);

System.out.println("Average: " + average);
输出结果为:Average: 3.0

4.将集合中的元素转换成另一种类型

假设有一个包含多个字符串的List集合,需要将其中的每个字符串转换成大写形式,可以使用流式编程来实现:

List<String> strings = Arrays.asList("apple", "banana", "orange", "pear", "grape");

List<String> upperCaseStrings = strings.stream()
                                        .map(String::toUpperCase)
                                        .collect(Collectors.toList());

System.out.println(upperCaseStrings);
输出结果为:[APPLE, BANANA, ORANGE, PEAR, GRAPE]

注意点

  1. 熟悉流的操作方法:流式编程提供了丰富的操作方法,如过滤、映射、排序、聚合等,需要熟悉这些方法的使用及其含义。
  2. 注意流的终止操作:流的操作是惰性的,需要使用终止操作才能触发流的执行。需要注意在使用流时,必须调用终止操作,否则流的操作不会执行。
  3. 考虑流的处理顺序:流的操作可以按照自然顺序进行处理,也可以通过指定顺序来进行处理。需要考虑流的处理顺序,以便能够得到正确的结果。
  4. 避免在流操作中修改原始数据:流操作是不会改变原始数据的,而是会返回一个新的流或新的集合。如果需要修改原始数据,应该使用集合操作。
  5. 注意流的性能:流式编程可以使代码更加简洁,但是也可能会对性能产生影响。在处理大量数据时,需要考虑流的性能问题。
  6. 理解并发处理:流式编程可以支持并发处理,但是需要注意并发处理可能会对代码的正确性和性能产生影响。需要理解并发处理的概念,并遵守相关的最佳实践。
  7. 选择合适的数据结构:流式编程可以适用于各种数据结构,但是不同的数据结构可能适合不同的流式操作。需要选择适合的数据结构以便获得最佳的性能和效果。

常用方法

  • **map():**将流中的每一个元素都应用一个函数,将其转换为另一个流
  • **filter():**根据一个谓词函数,过滤出符合条件的元素,返回一个新的流
  • **reduce():**将一个流中的元素结合起来,产生一个结果,可以使用lambda表达式来实现这个方法
  • **forEach():**对流中的每一个元素进行操作
  • **sorted():**对流中的元素进行排序,可以使用Comparator类来定义排序规则
  • **distinct():**返回一个包含流中所有不同元素的新流
  • **limit():**截取一个流中的前n个元素,返回一个新的流
  • **skip():**跳过一个流中的前n个元素,返回一个新的流
  • **flatMap():**将一个流中的每一个元素都转换成一个流,然后将这些流连接起来成为一个新的流

优缺点

优点

  1. 函数式编程:Stream 借助于Lambda表达式提供了更加优雅的函数式编程方式,使得代码更加简洁、易读、易维护。
  2. 惰性求值:Stream 提供了惰性求值的机制,只有在需要处理数据时才会进行处理,这种方式可以减少资源的占用,提高性能。
  3. 并行处理:Stream 可以很容易的实现并行处理,利用多核CPU来提高处理速度。
  4. 可以处理无限数据集:Stream 可以处理无限大的数据集,例如斐波那契数列,而传统的集合处理方式则无法处理这种数据集。

缺点

  1. 学习成本:对于新手来说,学习使用 Stream 的语法需要一定的学习成本。
  2. 代码可读性:有些复杂的 Stream 操作会降低代码的可读性,因此在使用 Stream 时需要慎重选择操作方式,以保证代码的可读性。
  3. 可能会影响性能:在某些情况下,Stream 的并行处理可能会影响性能,例如处理的数据量较小、处理过程中需要频繁的IO操作等。因此,在使用 Stream 时需要根据实际情况选择最优的操作方式。