stream是java 8引入的声明式数据处理特性,通过中间操作和终端操作简化集合处理。1. 创建方式包括:从集合调用stream()或parallelstream();2. 使用arrays.stream()转换数组;3. stream.of()直接传元素;4. generate()生成无限流需配合limit();5. iterate()创建有序无限流也需limit()。常用中间操作有filter过滤、map映射、flatmap展平嵌套结构、distinct去重、sorted排序、peek调试、limit截断、skip跳过。终端操作如foreach遍历、toarray转数组、reduce归约、collect收集结果、min/max找极值、count计数、anymatch/allmatch/nonematch判断匹配、findfirst/findany获取元素。适合使用并行流的场景包括大数据量、复杂计算、无依赖数据、cpu密集型任务且需线程安全。与传统循环相比,stream为声明式、内部迭代更简洁并支持并行处理。
Stream是Java 8引入的一个强大的特性,它允许你以声明式的方式处理集合数据,简化代码并提高效率。可以把它看作是数据流,你可以在上面执行各种操作,例如过滤、映射、排序等,最终得到想要的结果。
Stream的操作可以分为两种:中间操作和终端操作。中间操作返回一个新的Stream,允许你链式调用多个操作。终端操作则会消费Stream,产生一个结果或副作用。
创建Stream的方法有很多,最常见的几种方式包括:
立即学习“Java免费学习笔记(深入)”;
从集合创建: 这是最常用的方式,直接调用Collection接口的stream()或parallelStream()方法即可。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); Stream<String> stream = names.stream(); // 创建顺序流 Stream<String> parallelStream = names.parallelStream(); // 创建并行流
从数组创建: 使用Arrays.stream()方法可以将数组转换为Stream。
int[] numbers = {1, 2, 3, 4, 5}; IntStream stream = Arrays.stream(numbers);
使用Stream.of()方法: 可以直接将多个元素作为参数传递给Stream.of()方法来创建Stream。
Stream<String> stream = Stream.of("Apple", "Banana", "Orange");
使用Stream.generate()方法: 可以使用Stream.generate()方法生成一个无限流,需要提供一个Supplier函数来生成元素。注意: 无限流需要配合limit()方法来限制流的大小,否则会无限循环。
Stream<Double> randomStream = Stream.generate(Math::random).limit(10); // 生成10个随机数的流
使用Stream.iterate()方法: 可以使用Stream.iterate()方法生成一个有序的无限流,需要提供一个初始值和一个UnaryOperator函数来生成后续元素。同样,需要配合limit()方法来限制流的大小。
Stream<Integer> evenNumbers = Stream.iterate(0, n -> n + 2).limit(10); // 生成10个偶数的流
中间操作会返回一个新的Stream,允许你链式调用多个操作,对数据进行转换和过滤。常见的中间操作包括:
filter(Predicate predicate): 过滤Stream中的元素,只保留满足predicate条件的元素。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Anna"); Stream<String> filteredStream = names.stream().filter(name -> name.startsWith("A")); // 过滤出以"A"开头的名字
map(Function mapper): 将Stream中的每个元素映射为另一个元素,可以使用mapper函数进行转换。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); Stream<Integer> nameLengths = names.stream().map(String::length); // 将名字映射为名字的长度
flatMap(Function>,你想把它变成一个List
List<List<String>> nestedList = Arrays.asList( Arrays.asList("a", "b"), Arrays.asList("c", "d", "e") ); Stream<String> flattenedStream = nestedList.stream().flatMap(List::stream); // 将嵌套的List展平
distinct(): 去除Stream中重复的元素。
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 3); Stream<Integer> distinctStream = numbers.stream().distinct(); // 去除重复的数字
sorted(): 对Stream中的元素进行排序。可以传入Comparator来自定义排序规则。
List<String> names = Arrays.asList("Charlie", "Alice", "Bob"); Stream<String> sortedStream = names.stream().sorted(); // 默认按字母顺序排序 Stream<String> sortedStreamByLength = names.stream().sorted(Comparator.comparingInt(String::length)); // 按名字长度排序
peek(Consumer action): 对Stream中的每个元素执行action操作,但不会改变Stream的内容。这个操作通常用于调试,可以在Stream处理过程中查看元素的值。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); Stream<String> peekedStream = names.stream().peek(System.out::println); // 打印每个名字
limit(long maxSize): 截断Stream,只保留前maxSize个元素。
Stream<Integer> numbers = Stream.iterate(1, n -> n + 1); Stream<Integer> limitedStream = numbers.limit(10); // 只保留前10个数字
skip(long n): 跳过Stream中的前n个元素。
Stream<Integer> numbers = Stream.iterate(1, n -> n + 1); Stream<Integer> skippedStream = numbers.skip(5); // 跳过前5个数字
终端操作会消费Stream,产生一个结果或副作用。常见的终端操作包括:
forEach(Consumer action): 对Stream中的每个元素执行action操作。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); names.stream().forEach(System.out::println); // 打印每个名字
toArray(): 将Stream中的元素转换为数组。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); String[] nameArray = names.stream().toArray(String[]::new); // 转换为String数组
reduce(BinaryOperator accumulator): 将Stream中的元素归约为一个值。可以提供一个初始值,也可以不提供。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); int sum = numbers.stream().reduce(0, Integer::sum); // 计算所有数字的和,初始值为0 Optional<Integer> product = numbers.stream().reduce(Integer::sum); // 计算所有数字的积,没有初始值,返回Optional
collect(Collector collector): 将Stream中的元素收集到集合中。可以使用Collectors类提供的各种收集器,例如toList()、toSet()、toMap()等。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); List<String> nameList = names.stream().collect(Collectors.toList()); // 收集到List Set<String> nameSet = names.stream().collect(Collectors.toSet()); // 收集到Set Map<String, Integer> nameMap = names.stream().collect(Collectors.toMap(name -> name, String::length)); // 收集到Map,key为名字,value为名字的长度
min(Comparator comparator): 返回Stream中的最小值。需要提供一个Comparator来比较元素。
List<Integer> numbers = Arrays.asList(5, 2, 8, 1, 9); Optional<Integer> min = numbers.stream().min(Integer::compare); // 找到最小的数字
max(Comparator comparator): 返回Stream中的最大值。需要提供一个Comparator来比较元素。
List<Integer> numbers = Arrays.asList(5, 2, 8, 1, 9); Optional<Integer> max = numbers.stream().max(Integer::compare); // 找到最大的数字
count(): 返回Stream中元素的个数。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); long count = names.stream().count(); // 计算名字的个数
anyMatch(Predicate predicate): 判断Stream中是否存在任意一个元素满足predicate条件。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); boolean anyMatch = names.stream().anyMatch(name -> name.startsWith("A")); // 是否存在以"A"开头的名字
allMatch(Predicate predicate): 判断Stream中是否所有元素都满足predicate条件。
List<String> names = Arrays.asList("Alice", "Anna", "Amy"); boolean allMatch = names.stream().allMatch(name -> name.startsWith("A")); // 是否所有名字都以"A"开头
noneMatch(Predicate predicate): 判断Stream中是否没有元素满足predicate条件。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); boolean noneMatch = names.stream().noneMatch(name -> name.startsWith("Z")); // 是否没有名字以"Z"开头
findFirst(): 返回Stream中的第一个元素。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); Optional<String> first = names.stream().findFirst(); // 找到第一个名字
findAny(): 返回Stream中的任意一个元素。在并行流中,findAny()的效率通常比findFirst()更高。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); Optional<String> any = names.parallelStream().findAny(); // 找到任意一个名字
并行流可以利用多核CPU的优势,提高处理数据的效率。但是,并行流并非总是最佳选择。以下是一些需要考虑的因素:
一般来说,当数据量较大,操作比较复杂,且数据之间没有依赖性时,可以考虑使用并行流。
Stream和传统循环的主要区别在于:
总的来说,Stream提供了一种更简洁、更高效的数据处理方式。在合适的场景下,使用Stream可以显著提高代码的可读性和性能。
以上就是Java中Stream的用法_Java中Stream的操作指南的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号