Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
本文通过提供一些入门级的案例供初学者学习,让程序员写出高效率、干净、简洁的代码。
Stream是Java 8引入的一个用于处理集合数据的API。它是一种数据处理流,可以用于对集合进行高效的函数式操作。Stream提供了一组丰富的方法,可以进行过滤、映射、聚合、排序等操作,以及支持并行处理。
Stream流的主要特点包括:
序列性:Stream是一系列元素的集合视图,可以对这些元素进行各种操作。与集合不同的是,Stream并不存储数据,而是按需计算和处理数据。
不可变性:Stream的操作通常是非破坏性的,即对原始数据不产生修改。每个Stream操作都会返回一个新的Stream作为结果,原始数据保持不变。
延迟执行:Stream操作是延迟执行的,只有在终止操作(如forEach、collect等)被调用时才会实际触发计算。这种延迟执行机制使得流操作可以进行优化,只计算实际需要的数据。
函数式编程:Stream提供了一组函数式编程的方法,可以以声明式的方式操作数据,避免了显式的迭代和条件判断,使代码更简洁、易读。
通过使用Stream,可以以一种更简洁、更表达性的方式处理集合数据,同时还能够利用并行处理来提高性能。Stream提供了诸多方法,例如filter、map、reduce、collect等,可以根据需求对数据进行筛选、转换、汇总等操作,大大简化了集合数据的处理过程。
Stream流在处理数据时可以提供高效性的原因主要有以下几点:
延迟执行(Lazy Evaluation):Stream流的操作是延迟执行的,只有在终止操作被调用时才会进行实际的计算。这意味着在中间操作过程中,数据并没有被实际处理,而是形成了一个操作链。这种延迟执行的机制可以优化性能,只处理实际需要的数据,避免了不必要的计算。
并行处理(Parallel Processing):Stream流提供了并行处理的能力,可以充分利用多核处理器的优势,将数据划分为多个子任务并行处理。通过使用parallel()方法,可以将流转换为并行流,从而在处理大量数据时提升效率。
内部迭代(Internal Iteration):使用Stream流进行数据处理时,迭代过程由Stream库自动完成,无需手动编写迭代代码。Stream库通过内部迭代方式实现了数据的并行处理和优化,可以更好地利用底层的硬件资源。
代码简洁性和可读性:Stream流提供了一套丰富的操作方法,能够以一种更简洁、更声明式的方式处理数据。相比传统的循环和条件语句,Stream流代码更易读、易维护,减少了代码的复杂性,提高了开发效率。
List<String> names = List.of("Alice", "Bob", "Charlie");
Stream<String> stream = names.stream();
int[] numbers = {1, 2, 3, 4, 5};
IntStream stream = Arrays.stream(numbers);
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
long count = numbers.parallelStream()
.filter(n -> n % 2 == 0)
.count();
List<String> list = Arrays.asList("a", "b", "c");
// 遍历集合中,打印输出集合的每一项
list.stream()
.forEach(s-> System.out.println(s));
List<String> list = Arrays.asList("a", "b", "c");
list.stream()
.peek(s-> System.out.println("Peek: " + s))
.map(String::toUpperCase)
.forEach(System.out::println);
List<String> list = Arrays.asList("apple", "banana", "orange");
// 创建流
Stream<String> stream = list.stream();
// 筛选出长度大于 5 的元素
Stream<String> filteredStream = stream.filter(s -> s.length() > 5);
// 遍历筛选后的元素
filteredStream.forEach(System.out::println);
List<Integer> numbers = Arrays.asList(1, 2, 3, 2, 4, 3, 5, 1);
Stream<Integer> distinctNumbers = numbers.stream().distinct();
distinctNumbers.forEach(System.out::println);
输出结果:1,2,3,4,5
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Stream<Integer> limitedStream = numbers.stream().limit(5);
limitedStream.forEach(System.out::println);
List<String> fruits = Arrays.asList("apple", "banana", "orange", "grape", "mango");
Stream<String> limitedFruits = fruits.stream()
.filter(fruit -> fruit.length() > 5)
.limit(2);
limitedFruits.forEach(System.out::println);
以上代码输出结果
1
2
3
4
5
banana
orange
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 检查是否存在大于 3 的元素
boolean anyMatch = numbers.stream().anyMatch(n -> n > 3);
//输出结果:true
结合其他流操作使用:
List<String> fruits = Arrays.asList("apple", "banana", "orange", "grape");
// 检查是否存在以字母 "b" 开头的水果
boolean anyMatch = fruits.stream()
.filter(fruit -> fruit.startsWith("b"))
.anyMatch(fruit -> true);
//输出结果:true
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 检查是否所有元素都小于等于 5
boolean allMatch = numbers.stream().allMatch(n -> n <= 5);
//输出结果:true
结合其他流操作使用:
List<String> fruits = Arrays.asList("apple", "banana", "orange", "grape");
// 检查是否所有水果的长度都大于 3
boolean allMatch = fruits.stream()
.filter(fruit -> fruit.startsWith("b"))
.allMatch(fruit -> fruit.length() > 3);
//输出结果:false
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 检查是否不存在大于 5 的元素
boolean noneMatch = numbers.stream().noneMatch(n -> n > 5);
// 输出结果:true
结合其他流操作使用:
List<String> fruits = Arrays.asList("apple", "banana", "orange", "grape");
// 检查是否不存在以字母 "b" 开头的水果
boolean noneMatch = fruits.stream()
.filter(fruit -> fruit.startsWith("b"))
.noneMatch(fruit -> true);
// 输出结果:true
// 过滤出长度大于 4 的名字,然后将它们转换为大写,打印出最后的结果。
List names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream()
.filter(name -> name.length() > 4)
.map(String::toUpperCase)
.forEach(System.out::println);
// 输出结果:CHARLIE
List numbers = Arrays.asList(5, 2, 8, 1, 3);
numbers.stream().sorted()forEach(System.out::println);
// 输出结果:
// 1
// 2
// 3
// 5
// 8
List names = Arrays.asList("Alice", "Bob", "Charlie");
// 根据字符串长度对流中的元素进行排序
List result = names.stream().sorted(Comparator.comparing(String::length)).toList();
// 输出结果:
// Bob
// Alice
// Charlie
// 将集合中的元素进行排序后再输出。
List numbers = Arrays.asList(5, 2, 8, 1, 3);
List result = numbers.stream().sorted().toList();
System.out.println(result );
// 输出结果: [1, 2, 3, 5, 8]
List names = Arrays.asList("Alice", "Bob", "Charlie");
List names1 = names.stream()
.collect(Collectors.toList());
System.out.println(names1);
Set names2 = names.stream()
.collect(Collectors.toSet());
System.out.println(names2);
// 输出结果:
// [Alice, Bob, Charlie]
// [Alice, Bob, Charlie]