网站建设规划总结,莱阳网页定制,企业管理系统官网,购物网站开发计划书文章目录 Stream介绍什么是 Stream#xff1f; Stream中间操作过滤操作#xff08;filter#xff09;映射操作#xff08;map#xff09;排序操作#xff08;sorted#xff09;截断操作#xff08;limit 和 skip#xff09; Stream 的终止操作forEach 和 peek聚合操作… 文章目录 Stream介绍什么是 Stream Stream中间操作过滤操作filter映射操作map排序操作sorted截断操作limit 和 skip Stream 的终止操作forEach 和 peek聚合操作reduce匹配操作allMatch、anyMatch 和 noneMatch查找操作findFirst 和 findAny统计操作count、max 和 min Stream
介绍
Java Stream 的主要作用有以下几个方面
简化集合操作使用传统的 for 循环或迭代器来处理集合数据可能会导致冗长而复杂的代码。延迟计算流式操作允许你在处理数据之前定义一系列的操作步骤但只在需要结果时才会实际执行。这种延迟计算的特性意味着可以根据需要动态调整数据处理的操作流程提升效率。并行处理Java Stream 提供了并行流的支持可以将数据分成多个块进行并行处理从而充分利用多核处理器的性能优势提高代码的执行速度。函数式编程风格流式编程鼓励使用函数式编程的思想通过传递函数作为参数或使用 Lambda 表达式来实现代码的简化和灵活性。
为什么使用流式编程可以提高代码可读性和简洁性 声明式编程风格流式编程采用了一种声明式的编程风格你只需描述你想要对数据执行的操作而不需要显式地编写迭代和控制流语句。 链式调用流式编程使用方法链式调用的方式将多个操作链接在一起。每个方法都返回一个新的流对象这样你可以像“流水线”一样在代码中顺序地写下各种操作使代码逻辑清晰明了。 操作的组合流式编程提供了一系列的操作方法如过滤、映射、排序、聚合等这些方法可以按照需要进行组合使用。你可以根据具体的业务需求将这些操作串联起来形成一个复杂的处理流程而不需要编写大量的循环和条件语句。 减少中间状态传统的迭代方式通常需要引入中间变量来保存中间结果这样会增加代码的复杂度和维护成本。而流式编程将多个操作链接在一起通过流对象本身来传递数据避免了中间状态的引入。 减少循环和条件流式编程可以替代传统的循环和条件语句的使用。
什么是 Stream
Stream流是一个来自数据源的元素队列并支持聚合操作
元素是特定类型的对象形成一个队列。 Java中的Stream并不会存储元素而是按需计算。数据源 流的来源。 可以是集合数组I/O channel 产生器generator 等。聚合操作 类似SQL语句一样的操作 比如filter, map, reduce, find, match, sorted等。不可变性Stream 是不可变的它不会修改原始数据源也不会产生中间状态或副作用。每个操作都会返回一个新的流对象以保证数据的不可变性。 和以前的Collection操作不同 Stream操作还有两个基础的特征Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道 如同流式风格fluent style。 这样做可以对操作进行优化 比如延迟执行(laziness)和短路( short-circuiting)。内部迭代 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代 这叫做外部迭代。 Stream提供了内部迭代的方式 通过访问者模式(Visitor)实现。
Stream中的操作大体可以分为两类
中间操作将流一层层的进行处理并向下一层进行传递如 filter map sorted等。 中间操作又分为有状态(stateful)及无状态(stateless) 有状态必须等上一步操作完拿到全部元素后才可操作如sorted无状态该操作的数据不收上一步操作的影响如filter map 终止操作触发数据的流动并收集结果如collect findFirst forEach等。终止操作又分为短路操作(short-circuiting)及非短路操作(non-short-circuiting) 短路操作会在适当的时刻终止遍历类似于break如anyMatch findFirst等非短路操作会遍历所有元素如collect max等
Stream中间操作
过滤操作filter
过滤操作filter它接受一个 Predicate 函数作为参数用于过滤 Stream 中的元素。只有满足 Predicate 条件的元素会被保留下来而不满足条件的元素将被过滤掉。
过滤操作的语法如下
StreamT filter(Predicate? super T predicate)其中T 表示 Stream 元素的类型predicate 是一个函数式接口 Predicate 的实例它的泛型参数和 Stream 元素类型一致,并且predicate返回的值必须是boolean类型因为需要通过真假值判断是否要过滤该值。
使用过滤操作可以根据自定义的条件来筛选出符合要求的元素从而对 Stream 进行精确的数据过滤。
下面是一个示例演示如何使用过滤操作筛选出一个整数流中的大于三的数 ListInteger numbers Arrays.asList(1, 2, 3, 4, 5);
// 生成流式对象
// StreamInteger stream numbers.stream();ListInteger listnumbers.stream().filter((x)-{return x3;} //lambda表达式 可简化成下面的写法
// x-x3).toList();System.out.println(number中大于3的数: list.toString());
映射操作map
映射操作map它接受一个 Function 函数作为参数用于对 Stream 中的每个元素进行映射转换生成一个新的 Stream。
映射操作的语法如下
R StreamR map(Function? super T, ? extends R mapper)其中T 表示原始 Stream 的元素类型R 表示映射后的 Stream 的元素类型mapper 是一个函数式接口 Function 的实例可以进行不同的映射操作.
下面是一个示例演示如何使用映射操作将一个字符串流中的每个字符串转换为其长度 ListString numbers Arrays.asList(apple, banana, cherry);
// 生成流式对象
// StreamInteger stream numbers.stream();numbers.stream().map(String::length).forEach(System.out::println);在这个示例中我们首先创建了一个包含字符串的 Stream并调用 map() 方法传入String::length表示要将每个字符串转换为其长度。然后通过 forEach() 方法遍历输出结果。
注意: 映射操作可能引发空指针异常NullPointerException因此在执行映射操作时应确保原始 Stream 中不包含空值并根据具体情况进行空值处理。
排序操作sorted
排序操作sorted是 Stream API 中的一种常用操作方法它用于对 Stream 中的元素进行排序。排序操作可以按照自然顺序或者使用自定义的比较器进行排序。
排序操作的语法如下
StreamT sorted() StreamT sorted(Comparator? super T comparator)第一种语法形式中sorted() 方法会根据元素的自然顺序进行排序。如果元素实现了 Comparable 接口并且具备自然顺序那么可以直接调用该方法进行排序。 第二种语法形式中sorted(Comparator? super T comparator) 方法接受一个比较器Comparator作为参数用于指定元素的排序规则。通过自定义比较器可以对非 Comparable 类型的对象进行排序。
下面是一个示例演示如何使用排序操作对一个字符串流进行排序 ListString numbers Arrays.asList(apple, banana, cherry);
// 生成流式对象
// StreamInteger stream numbers.stream();numbers.stream().sorted().forEach(System.out::println);
输出
apple
banana
cherry注意: 排序操作可能会影响程序的性能特别是对于大型数据流或者复杂的排序规则。因此在实际应用中需要根据具体情况进行权衡和优化选择合适的算法和数据结构来提高排序的效率。
截断操作limit 和 skip
截断操作limit和skip用于在处理流的过程中对元素进行截断。
limit(n)保留流中的前n个元素返回一个包含最多n个元素的新流。如果流中元素少于n个则返回原始流。skip(n)跳过流中的前n个元素返回一个包含剩余元素的新流。如果流中元素少于n个则返回一个空流。 下面分别详细介绍这两个方法的使用。
注意: 在使用截断操作时需要注意流的有界性。如果流是无界的例如 Stream.generate()那么使用 limit() 方法可能导致程序陷入无限循环而使用 skip() 方法则没有意义。
Stream 的终止操作
forEach 和 peek
forEach和peek都是Stream API中用于遍历流中元素的操作方法它们在处理流的过程中提供了不同的功能和使用场景。
forEach forEach是一个终端操作方法它接受一个Consumer函数作为参数对流中的每个元素执行该函数。forEach会遍历整个流对每个元素执行相同的操作。
示例代码
ListString names Arrays.asList(Alice, Bob, Charlie);
names.stream().forEach(System.out::println);peek peek是一个中间操作方法它接受一个Consumer函数作为参数对流中的每个元素执行该函数。与forEach不同的是peek方法会返回一个新的流该流中的元素和原始流中的元素相同。
示例代码
ListString names Arrays.asList(Alice, Bob, Charlie);
ListString upperCaseNames names.stream().map(String::toUpperCase).peek(System.out::println).toList();聚合操作reduce
reduce和collect都是Stream API中用于聚合操作的方法它们可以将流中的元素进行汇总、计算和收集。
reduce reduce是一个终端操作方法它接受一个BinaryOperator函数作为参数对流中的元素逐个进行合并操作最终得到一个结果。该方法会将流中的第一个元素作为初始值然后将初始值与下一个元素传递给BinaryOperator函数进行计算得到的结果再与下一个元素进行计算以此类推直到遍历完所有元素。
示例代码 ListInteger numbers Arrays.asList(1, 2, 3, 4, 5);numbers.stream().reduce(Integer::sum).ifPresent(System.out::println);//输出结果15在这个示例中我们创建了一个包含整数的List并通过stream()方法将其转换为流。然后使用reduce方法对流中的元素进行求和操作将每个元素依次相加得到结果15。
匹配操作allMatch、anyMatch 和 noneMatch
在 Stream API 中allMatch、anyMatch 和 noneMatch 是用于进行匹配操作的方法它们可以用来检查流中的元素是否满足特定的条件。
allMatch allMatch 方法用于判断流中的所有元素是否都满足给定的条件。当流中的所有元素都满足条件时返回 true如果存在一个元素不满足条件则返回 false。
anyMatch anyMatch 方法用于判断流中是否存在至少一个元素满足给定的条件。当流中至少有一个元素满足条件时返回 true如果没有元素满足条件则返回 false。
在这个示例中我们创建了一个包含整数的 List并通过 stream() 方法将其转换为流。然后使用 anyMatch 方法判断流中是否存在偶数。由于列表中存在偶数所以返回 true。
noneMatch noneMatch 方法用于判断流中的所有元素是否都不满足给定的条件。当流中没有元素满足条件时返回 true如果存在一个元素满足条件则返回 false。
示例代码
ListInteger numbers Arrays.asList(1, 2, 3, 4, 5);
boolean allEven numbers.stream().allMatch(n - n % 2 0);
System.out.println(allEven); // 输出结果: false
boolean hasEven numbers.stream().anyMatch(n - n % 2 0);
System.out.println(hasEven); // 输出结果: true
boolean noneNegative numbers.stream().noneMatch(n - n 0);
System.out.println(noneNegative); // 输出结果: true
查找操作findFirst 和 findAny
在 Stream API 中findFirst 和 findAny 是用于查找操作的方法它们可以用来从流中获取满足特定条件的元素。
findFirst findFirst 方法用于返回流中的第一个元素。它返回一个 Optional 对象如果流为空则返回一个空的 Optional如果流非空则返回流中的第一个元素的 Optional。
findAny findAny 方法用于返回流中的任意一个元素。它返回一个 Optional 对象如果流为空则返回一个空的 Optional如果流非空则返回流中的任意一个元素的 Optional。在顺序流中通常会返回第一个元素而在并行流中由于多线程的处理可能返回不同的元素。
示例代码 ListString names Arrays.asList(Alice, Bob, Charlie);
OptionalString first names.stream().findFirst();
first.ifPresent(System.out::println); // 输出结果: AliceListInteger numbers Arrays.asList(1, 2, 3, 4, 5);
OptionalInteger any numbers.stream().filter(n - n % 2 0).findAny();
any.ifPresent(System.out::println); // 输出结果: 2 或 4取决于并行处理的结果统计操作count、max 和 min
在 Stream API 中count、max 和 min 是用于统计操作的方法它们可以用来获取流中元素的数量、最大值和最小值。
count count 方法用于返回流中元素的数量。它返回一个 long 类型的值表示流中的元素个数。
max max 方法用于返回流中的最大值。
min min 方法用于返回流中的最小值。它返回一个 Optional 对象如果流为空则返回一个空的 Optional如果流非空则返回流中的最小值的 Optional。
示例代码
ListInteger numbers Arrays.asList(1, 2, 3, 4, 5);
long count numbers.stream().count();
System.out.println(count); // 输出结果: 5OptionalInteger max numbers.stream().max(Integer::compareTo);
max.ifPresent(System.out::println); // 输出结果: 5OptionalInteger min numbers.stream().min(Integer::compareTo);
min.ifPresent(System.out::println); // 输出结果: 1