当前位置: 首页 > article >正文

Stream API 的设计融合了多个经典设计模式

Stream API 的设计融合了多个经典设计模式:

1. 策略模式(Strategy Pattern)

策略模式定义了一个算法的家族,将每个算法封装起来,并使它们可以互换。Stream API 中的每个操作(如 filter(), map())都是一个策略,它允许用户以灵活的方式组合这些操作。

import java.util.*;
import java.util.stream.*;

public class StrategyPatternDemo {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        // 策略1: 过滤偶数
        List<Integer> evenNumbers = numbers.stream()
                                           .filter(n -> n % 2 == 0)  // 策略1
                                           .collect(Collectors.toList());

        // 策略2: 将每个数字加倍
        List<Integer> doubledNumbers = numbers.stream()
                                              .map(n -> n * 2)           // 策略2
                                              .collect(Collectors.toList());

        System.out.println("Even Numbers: " + evenNumbers);
        System.out.println("Doubled Numbers: " + doubledNumbers);
    }
}

输出:

Even Numbers: [2, 4, 6, 8, 10]
Doubled Numbers: [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

上面代码中,filtermap 都是不同的策略操作,它们可以灵活地组合在一起。你可以选择不同的策略(如筛选偶数或将数字加倍),并将它们组合成一个管道来处理数据。

2. 装饰者模式(Decorator Pattern)

Stream API 中的中间操作(如 filter(), map())是典型的装饰者模式。每个中间操作都会返回一个新的流对象,逐步增强原始流的功能。

import java.util.*;
import java.util.stream.*;

public class DecoratorPatternDemo {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        // 使用装饰者模式: 先过滤偶数,再将每个数字加倍
        List<Integer> result = numbers.stream()
                                      .filter(n -> n % 2 == 0)   // 装饰者1: 筛选偶数
                                      .map(n -> n * 2)           // 装饰者2: 每个数字加倍
                                      .collect(Collectors.toList());

        System.out.println("Processed Numbers: " + result);
    }
}

输出:

Processed Numbers: [4, 8, 12, 16, 20]

上面代码中,filtermap 是装饰者模式的实现。每个中间操作都返回一个新的流,逐步增强原始流的功能。最终的流会先过滤偶数,再将这些偶数乘以 2。

3. 惰性求值(Lazy Evaluation)

Stream API 的惰性求值意味着中间操作不会立即执行,只有在遇到终端操作时,流才会开始计算。以下是一个示例:

import java.util.*;
import java.util.stream.*;

public class LazyEvaluationDemo {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        // 惰性求值,只有在终端操作(forEach)执行时,流才会开始计算
        numbers.stream()
               .filter(n -> {
                   System.out.println("Filtering: " + n);
                   return n % 2 == 0;  // 过滤偶数
               })
               .map(n -> {
                   System.out.println("Mapping: " + n);
                   return n * 2;       // 每个数字加倍
               })
               .forEach(n -> System.out.println("Final Result: " + n));  // 输出结果
    }
}

输出:

Filtering: 1
Filtering: 2
Mapping: 2
Final Result: 4
Filtering: 3
Filtering: 4
Mapping: 4
Final Result: 8
Filtering: 5
Filtering: 6
Mapping: 6
Final Result: 12
Filtering: 7
Filtering: 8
Mapping: 8
Final Result: 16
Filtering: 9
Filtering: 10
Mapping: 10
Final Result: 20

上面代码中,filtermap 都是懒执行的操作。filtermap 的计算只有在调用终端操作(forEach)时才会开始执行。可以看到,只有经过过滤和映射的元素才会打印出来。

4. 合并模式(Merging / ForkJoin)

并行流实现了合并模式,它通过 ForkJoinPool 将任务拆分成子任务并行执行,然后合并结果。以下是一个简单的并行流的示例:

import java.util.*;
import java.util.stream.*;

public class ForkJoinDemo {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        // 使用并行流执行计算
        int sum = numbers.parallelStream()
                          .map(n -> {
                              System.out.println("Processing: " + n + " in thread: " + Thread.currentThread().getName());
                              return n;
                          })
                          .reduce(0, Integer::sum);

        System.out.println("Total Sum: " + sum);
    }
}

输出(不同的线程名可能会有所不同):

Processing: 7 in thread: main
Processing: 6 in thread: main
Processing: 8 in thread: ForkJoinPool.commonPool-worker-2
Processing: 9 in thread: main
Processing: 10 in thread: main
Processing: 2 in thread: ForkJoinPool.commonPool-worker-2
Processing: 3 in thread: ForkJoinPool.commonPool-worker-1
Processing: 1 in thread: ForkJoinPool.commonPool-worker-2
Processing: 5 in thread: main
Processing: 4 in thread: ForkJoinPool.commonPool-worker-1
Total Sum: 55

在上面代码中,parallelStream() 会将任务分成多个子任务并行执行。每个子任务在不同的线程中处理数据,最终通过 reduce 操作将结果合并(在这个例子中是求和)。

总结:

  • 策略模式:Stream 中的每个操作(如 filter()map())都代表一个策略,可以灵活组合。
  • 装饰者模式:中间操作是装饰者,逐步增强流的功能,操作不会修改原始流。
  • 惰性求值:Stream 的中间操作(如 filter()map())在终端操作(如 forEach())触发时才会执行。
  • 合并模式:并行流通过将任务拆分成多个子任务并行执行,最终合并结果,适合多核处理器的计算密集型任务。

http://www.kler.cn/a/457231.html

相关文章:

  • 1月第二讲:WxPython跨平台开发框架之图标选择界面
  • archlinux使用
  • docker学习记录-部署若依springcloud项目
  • idea报错:There is not enough memory to perform the requested operation.
  • 十个Scala的小知识
  • NXP i.MX8系列平台开发讲解 - 5.4 调试篇 - 掌握perf 工具调试(一)
  • vulnhub-Raven2靶机的测试报告
  • MFC小知识:CEdit::GetSel函数的使用
  • 智能工厂的设计软件 应用场景的一个例子:为AI聊天工具添加一个知识系统 之3 帮助AI聊天工具中提问者正确描述问题
  • 【HarmonyOS】如何读取Raw下的JSON文件内容
  • IP属地和所在地不一致什么意思?怎么换成另外一个地方的
  • 嵌入式小白
  • leetcode-----mysql
  • 【java基础】时间
  • WAV文件双轨PCM格式详细说明及C语言解析示例
  • 计算机图形学知识点汇总
  • 保险科技“数智化+”赋能险企高质量发展
  • 72.是否可以把所有Bean都通过Spring容器来管理?(Spring的applicationContext.xml中配置全局扫 描)
  • 基于Pycharm与数据库的新闻管理系统(2)Redis
  • 内网渗透思路amp;相关服务爆破以及提权
  • SpringBoot使用外置的Servlet容器(详细步骤)
  • CH340系列芯片驱动电路·CH340系列芯片驱动!!!
  • 鸿蒙next之如何实现防截屏功能
  • 在 CentOS 系统上安装 ClickHouse
  • Es搭建——单节点——Linux
  • 【FPGA】ISE13.4操作手册,新建工程示例