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

避免魔法值和多层if的关键:编程范式和设计模式

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、案例分析
  • 二、技术手段
    • 函数式接口
    • 在枚举中
  • 三、优化后完整代码
  • 总结


前言

提示:避免魔法值和多层if的关键:编程范式和设计模式:
设计原则:
开放封闭原则(OCP):通过扩展枚举实现新功能,而非修改现有代码
单一职责原则(SRP):将区域ID与处理逻辑解耦,各自独立变化

  1. 枚举类 封装区域ID与处理逻辑的映射关系
  2. BiConsumer 函数式接口实现动态方法调用
  3. Stream API 函数式遍历替代过程式循环

提示:以下是本篇文章正文内容,下面案例可供参考

一、案例分析

private void saveAreaStatisticsDaily(List<ObjectA> result, LocalDateTime CCCTime) {ObjectB objectB = new ObjectB();result.stream().forEach(po -> {if(po.getAreaId().equals("1669")){objectB.setRightOfCCCrOAD(po.getFlow());}else if (po.getAreaId().equals("1670")){objectB.setLeftOfCCCrOAD(po.getFlow());}else if (po.getAreaId().equals("1671")){objectB.setUndergroundRingrOAD(po.getFlow());}else if (po.getAreaId().equals("1672")){objectB.setXtUnderpassrOAD(po.getFlow());}else if (po.getAreaId().equals("1673")){objectB.setJbxRightOfUnderpassrOAD(po.getFlow());}else if (po.getAreaId().equals("1674")){objectB.setJbxLeftOfUnderpassrOAD(po.getFlow());}});objectB.setCCCTime(CCCTime);objectB.setFlow(result.stream().mapToInt(ObjectA::getFlow).sum());dailyStatisticsService.save(objectB);}

问题类型 具体表现

  1. 魔法值 区域ID(如"1669")直接硬编码在业务逻辑中
  2. 多层条件判断 大量if-else分支导致代码臃肿
  3. 违反OCP原则 新增区域需修改原有方法,影响稳定性
  4. 可测试性差 条件分支多,单元测试需覆盖所有分支,维护成本高

二、技术手段

函数式接口

函数式编程模式
函数式编程模式是一种设计模式,它将程序分解为一组函数,每个函数都是一个独立的计算。这种模式可以帮助程序员更好地组织代码,提高代码的可读性和可维护性。

enum AreaIdMapping {objectB_1669("1669", (po, value) -> po.setRightOfCrossobjectB(value)),objectB_1670("1670", (po, value) -> po.setLeftOfCrossobjectB(value)),objectB_1671("1671", ObjectB::setUndergroundRingobjectB),objectB_1672("1672", ObjectB::setXtUnderpassobjectB),objectB_1673("1673", ObjectB::setJbxRightOfUnderpassobjectB),objectB_1674("1674", ObjectB::setJbxLeftOfUnderpassobjectB);private final String areaId;private final BiConsumer<ObjectB, Integer> setter;AreaIdMapping(String areaId, BiConsumer<ObjectB, Integer> setter) {this.areaId = areaId;this.setter = setter;}public void apply(ObjectB po, int flow) {setter.accept(po, flow);}private static final Map<String, AreaIdMapping> BY_AREA_ID = Arrays.stream(values()).collect(Collectors.toMap(AreaIdMapping::getAreaId, Function.identity()));public static Optional<AreaIdMapping> fromAreaId(String areaId) {return Optional.ofNullable(BY_AREA_ID.get(areaId));}public String getAreaId() {return areaId;}}

BiConsumer<T, U> 是 Java 中的一个函数式接口(Functional Interface)。函数式接口指的是仅有一个抽象方法的接口,它们可以用于支持 Lambda 表达式或方法引用。BiConsumer<T, U> 接口位于 java.util.function 包中,它代表了一个接受两个输入参数执行操作且没有返回结果的操作。

private final BiConsumer<ObjectB, Integer> setter;@FunctionalInterface
public interface BiConsumer<T, U> {void accept(T t, U u);
}

BiConsumer<T, U> 接口包含一个名为 accept 的抽象方法:
此方法接收两个参数,第一个参数的类型为 T,第二个参数的类型为 U,不返回任何结果(即返回类型为 void)

作用:接收两个参数(ObjectB实例和流量值),执行赋值操作
优势:将方法调用抽象为可传递的行为参数

例子: 打印出两个数值的和。你可以使用 BiConsumer 来实现这个功能:

BiConsumer<Integer, Integer> sumPrinter = (a, b) -> System.out.println("Sum: " + (a + b));
sumPrinter.accept(5, 10); // 输出: Sum: 15

开放封闭原则:软件实体(类、模块等)应该是可扩展的,但不可修改的。

实际的应用场景,比如使用Consumer处理集合元素,用Predicate进行过滤,用Function进行数据转换,这样用户能更好地将理论应用到实际项目中

函数式编程核心接口

  1. Function<T, R> 转化器
    作用:接收一个输入值(T),返回处理后的结果(R)
    常见场景:数据转换、链式处理
// 字符串转整型
Function<String, Integer> strToInt = s -> Integer.parseInt(s);
int num = strToInt.apply("123"); // 123// 组合函数:先平方再转字符串
Function<Integer, Integer> square = x -> x * x;
Function<Integer, String> toString = x -> "Result: " + x;
Function<Integer, String> pipeline = square.andThen(toString);
System.out.println(pipeline.apply(3)); // "Result: 9"
  1. Consumer(消费者)
    作用:接收输入值(T),无返回值(void)
    常见场景:遍历集合、日志打印、资源处理
// 打印集合元素
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(name -> System.out.println("Name: " + name));// 组合消费者
Consumer<String> log = s -> System.out.println("[LOG] " + s);
Consumer<String> save = s -> repository.save(s);
Consumer<String> pipeline = log.andThen(save);
pipeline.accept("Data");
  1. Supplier(提供者)
    作用:无输入参数,返回一个值(T)

常见场景:延迟计算、对象工厂、配置获取

// 生成随机ID
Supplier<String> idGenerator = () -> UUID.randomUUID().toString();
String id = idGenerator.get(); // "550e8400-e29b-41d4-a716-446655440000"// 懒加载配置
Supplier<Config> configLoader = () -> loadConfigFromDB();
Config config = configLoader.get();
  1. Predicate(断言)
    作用:接收输入值(T),返回布尔判断结果

常见场景:数据过滤、条件验证

// 过滤偶数
Predicate<Integer> isEven = n -> n % 2 == 0;
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
numbers.stream().filter(isEven).forEach(System.out::println); // 2,4// 组合断言
Predicate<String> validLength = s -> s.length() >= 6;
Predicate<String> hasDigit = s -> s.matches(".*\\d.*");
Predicate<String> strongPassword = validLength.and(hasDigit);
boolean isValid = strongPassword.test("pass123"); // true

进阶接口与应用

  1. BiFunction<T, U, R>(双参数转换)
BiFunction<Integer, Integer, Double> power = (base, exp) -> Math.pow(base, exp);
Double result = power.apply(2, 3); // 8.0
  1. UnaryOperator(一元操作)
    本质:Function<T, T> 的特殊形式
UnaryOperator<String> trim = s -> s.trim();
String clean = trim.apply("  hello  "); // "hello"
  1. 方法引用(语法糖)

四种形式:

// 静态方法
Function<String, Integer> parser = Integer::parseInt;// 实例方法
Consumer<String> printer = System.out::println;// 对象方法
String str = "example";
Supplier<Integer> lengthSupplier = str::length;// 构造方法
Supplier<List<String>> listFactory = ArrayList::new;

实战应用场景

  1. 集合处理(Stream API)
List<Product> products = productRepository.findAll();// 过滤 + 转换
List<String> expensiveNames = products.stream().filter(p -> p.getPrice() > 100).map(Product::getName).toList();
  1. 策略模式
Map<String, Function<Order, BigDecimal>> discountStrategies = new HashMap<>();
discountStrategies.put("VIP", order -> order.getTotal().multiply(0.8));
discountStrategies.put("NEW_USER", order -> order.getTotal().subtract(50));BigDecimal finalPrice = discountStrategies.get(userType).apply(order);
  1. 回调机制
public void processFile(String path, Consumer<String> lineProcessor) {try (BufferedReader reader = new BufferedReader(new FileReader(path))) {String line;while ((line = reader.readLine()) != null) {lineProcessor.accept(line);}}
}// 使用
processFile("data.txt", line -> {if (line.contains("ERROR")) {alertService.notify(line);}
});
  1. 链式校验
Predicate<User> nameValid = u -> u.getName().length() >= 2;
Predicate<User> emailValid = u -> u.getEmail().contains("@");
Predicate<User> ageValid = u -> u.getAge() >= 18;Predicate<User> fullCheck = nameValid.and(emailValid).and(ageValid);
boolean isValid = fullCheck.test(user);

最佳实践与避坑指南

  1. 保持简洁性

避免在Lambda中编写超过3行的逻辑,复杂逻辑应封装为方法

// 反例
list.forEach(x -> {// 10行复杂处理...
});// 正例
list.forEach(this::processItem);
  1. 避免状态修改

函数式代码应无副作用,不修改外部变量

// 危险操作
int[] counter = {0};
list.forEach(x -> counter[0]++);// 安全替代
long count = list.stream().count();
  1. 优先使用已有接口

不需要自定义函数式接口时,尽量使用 java.util.function 中的标准接口

  1. 异常处理

Lambda中处理异常需显式捕获

list.forEach(s -> {try {process(s);} catch (IOException e) {throw new RuntimeException(e);}
});

在枚举中

BiConsumer<CheckpointAreaDayStatisticsPO, Integer> 被用来存储不同区域对应的设置方法引用。这允许 AreaIdMapping 枚举中的每个实例都携带一个特定的方法,该方法可以应用于 CheckpointAreaDayStatisticsPO 对象,并传递一个整型参数。这种方法避免了编写大量的 if-else 或 switch-case 语句来决定应该调用哪个方法,使得代码更加简洁、清晰和易于维护。例如:

enum AreaIdMapping {TUNNEL_1669("1669", CheckpointAreaDayStatisticsPO::setRightOfCrossTunnel),// 其他枚举常量...private final String areaId;private final BiConsumer<CheckpointAreaDayStatisticsPO, Integer> setter;AreaIdMapping(String areaId, BiConsumer<CheckpointAreaDayStatisticsPO, Integer> setter) {this.areaId = areaId;this.setter = setter;}public void apply(CheckpointAreaDayStatisticsPO po, int flow) {setter.accept(po, flow);}// ...其他方法...
}

枚举类(Enum)在Java中是一个非常强大和灵活的工具,适用于多种不同的场景。它们可以用于定义一组固定的常量、实现简单的状态机、管理配置选项等。以下是几种常见的应用方式及示例:

最常见的用途之一是定义一组固定的常量值。例如,表示一周中的天数:

public enum DayOfWeek {MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
}

枚举还可以携带属性和方法,使得每个枚举实例能够包含额外的信息。例如,颜色及其对应的RGB值:

public enum Color {RED(255, 0, 0), GREEN(0, 255, 0), BLUE(0, 0, 255);private final int r, g, b;Color(int r, int g, int b) {this.r = r;this.g = g;this.b = b;}public String getRGB() {return "(" + r + ", " + g + ", " + b + ")";}
}

实现接口的枚举
枚举可以实现接口,允许为不同枚举值提供具体的行为实现。例如,支付方式的不同处理逻辑:

public interface PaymentMethodProcessor {void processPayment(double amount);
}public enum PaymentMethod implements PaymentMethodProcessor {CREDIT_CARD {@Overridepublic void processPayment(double amount) {System.out.println("Processing credit card payment of $" + amount);}},PAYPAL {@Overridepublic void processPayment(double amount) {System.out.println("Processing PayPal payment of $" + amount);}};
}

状态模式
枚举非常适合用来实现简单状态机。例如,订单的状态变化:

public enum OrderStatus {PENDING, SHIPPED, DELIVERED, CANCELLED;public boolean canTransitionTo(OrderStatus newState) {switch (this) {case PENDING:return newState == SHIPPED || newState == CANCELLED;case SHIPPED:return newState == DELIVERED;case DELIVERED:case CANCELLED:return false;default:throw new IllegalArgumentException();}}
}

枚举与工厂模式结合
枚举可以作为工厂模式的一部分,用于创建对象。例如,根据不同的数据库类型创建相应的连接对象:

public enum DatabaseType {MYSQL, POSTGRESQL;public Connection createConnection(String url, String username, String password) throws SQLException {switch (this) {case MYSQL:// 返回MySQL数据库连接return DriverManager.getConnection(url, username, password);case POSTGRESQL:// 返回PostgreSQL数据库连接return DriverManager.getConnection(url, username, password);default:throw new UnsupportedOperationException("Unsupported database type");}}
}

通过这些例子,可以看到枚举类不仅可以用来定义一组固定的常量,还可以携带数据、实现接口、作为状态机的一部分,甚至是作为工厂模式的一部分来创建对象。这使得枚举成为Java编程中一个非常有用且多功能的工具。

三、优化后完整代码

优化后代码

  private void saveAreaStatisticsDaily(List<ObjectA> result, LocalDateTime crossTime) {ObjectB objectB = new ObjectB();// 使用forEach遍历每个ObjectA对象,并根据areaId设置相应的流量result.forEach(po ->AreaIdMapping.fromAreaId(po.getAreaId()).ifPresent(mapping -> mapping.apply(objectB, po.getFlow())));// 设置crossTime和总流量objectB.setCrossTime(crossTime);objectB.setFlow(result.stream().mapToInt(ObjectA::getFlow).sum());dailyStatisticsService.save(objectB);}enum AreaIdMapping {objectB_1669("1669", (po, value) -> po.setRightOfCrossobjectB(value)),objectB_1670("1670", (po, value) -> po.setLeftOfCrossobjectB(value)),objectB_1671("1671", ObjectB::setUndergroundRingobjectB),objectB_1672("1672", ObjectB::setXtUnderpassobjectB),objectB_1673("1673", ObjectB::setJbxRightOfUnderpassobjectB),objectB_1674("1674", ObjectB::setJbxLeftOfUnderpassobjectB);private final String areaId;private final BiConsumer<ObjectB, Integer> setter;AreaIdMapping(String areaId, BiConsumer<ObjectB, Integer> setter) {this.areaId = areaId;this.setter = setter;}public void apply(ObjectB po, int flow) {setter.accept(po, flow);}private static final Map<String, AreaIdMapping> BY_AREA_ID = Arrays.stream(values()).collect(Collectors.toMap(AreaIdMapping::getAreaId, Function.identity()));public static Optional<AreaIdMapping> fromAreaId(String areaId) {return Optional.ofNullable(BY_AREA_ID.get(areaId));}public String getAreaId() {return areaId;}}

总结

通过函数式接口与枚举的结合,实现了 行为参数化,使代码更符合现代编程范式。这种模式不仅适用于本例,还可广泛应用于状态机、策略选择等场景,是提升代码质量的利器。

相关文章:

避免魔法值和多层if的关键:编程范式和设计模式

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、案例分析二、技术手段函数式接口在枚举中 三、优化后完整代码总结 前言 提示&#xff1a;避免魔法值和多层if的关键&#xff1a;编程范式和设计模式&#…...

第六课:数据存储三剑客:CSV/JSON/MySQL

在Python的数据存储与处理领域&#xff0c;CSV、JSON和MySQL被广大开发者誉为“数据存储三剑客”。它们各自在不同的场景下发挥着重要作用&#xff0c;无论是简单的数据交换、轻量级的数据存储&#xff0c;还是复杂的关系型数据库管理&#xff0c;都能找到它们的身影。本文将详…...

Qt常用控件之表格QTableWidget

表格QTableWidget QTableWidget 是一个表格控件&#xff0c;行和列交汇形成的每个单元格&#xff0c;是一个 QTableWidgetItem 对象。 1. QTableWidget属性 QTableWidget 的属性只有两个&#xff1a; 属性说明rowCount当前行的个数。columnCount当前列的个数。 2. QTableW…...

基于websocket的多用户网页五子棋 --- 测试报告

目录 功能测试自动化测试性能测试 功能测试 1.登录注册页面 2.游戏大厅页面 3.游戏房间页面 自动化测试 1.使用脑图编写web自动化测试用例 2.创建自动化项目&#xff0c;根据用例通过selenium来实现脚本 根据脑图进行测试用例的编写&#xff1a; 每个页面一个测试类&am…...

TypeError: Cannot assign to read only property ‘xxx‘ of object ‘#<Object>‘

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 &#x1f35a; 蓝桥云课签约作者、…...

SyntaxError: Unexpected token ‘xxx‘

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 &#x1f35a; 蓝桥云课签约作者、…...

简记_开关电源基础知识(二)

一、控制器与稳压器 假设开关损耗、导通损耗、驱动损耗的变化远小于输出功率的变化&#xff08;可忽略&#xff09;&#xff0c;则占空比越大&#xff0c;Po越大&#xff0c;效率越高。 二、同步与非同步 同步是采用通态电阻极低的MOSFET来取代整流二极管&#xff0c;以降低整…...

grum-与gam-词源故事

“grum”词根的含义主要与“咕隆、发哼声、咕咕叫、发隆隆声”等相关。在16世纪90年代后&#xff0c;这个词开始被用来表示发出低沉持续的咆哮声或隆隆声&#xff0c;类似于饥饿的胃或某些动物发出的声音。 早期的富贵家族经常雇佣人去干活&#xff0c;体力活很容易因为劳工过…...

联合索引关于In和范围查询影响索引使用的情况分析

索引类型 1、unique &#xff0c;唯一索引 2、normal&#xff0c;普通索引 3、fulltext, 全文索引 4、spatial&#xff0c;空间索引 样例 三个字段的联合索引&#xff0c;走一个字段是key_len是5&#xff0c;三个是15. 联合索引关于 使用in是不影响后续列 范围查询大于或小于…...

【目标检测】【NeuralPS 2023】Gold-YOLO:通过收集与分发机制实现的高效目标检测器

Gold-YOLO&#xff1a; Efficient Object Detector via Gather-and-Distribute Mechanism Gold-YOLO&#xff1a;通过收集与分发机制实现的高效目标检测器 0.论文摘要 在过去的几年中&#xff0c;YOLO系列模型已成为实时目标检测领域的领先方法。许多研究通过修改架构、增强数…...

2025上软考下周开启报名!附报考流程和常见问题解答

报名时间 &#xff1a;3月10日开始报名&#xff08;以当地报名时间为准&#xff09; 考试时间 &#xff1a;2025年5月24日~27日&#xff08;具体时间以准考证为准&#xff09; 报名网址 &#xff1a;中国计算机技术职业资格网(https://bm.ruankao.org.cn/sign/welcome) 目前已…...

PPT 小黑第16套

对应大猫19 在excel中复制表格 粘贴-选择性粘贴 -粘贴链接 业务部门和档案管理部门 剩下都是他们的下属级别 业务部门下面的选中按Tab 再选中Tab降级变成所属...

Swagger-01.介绍和使用方式

一.Swagger介绍 有了接口文档&#xff0c;我们就可以根据接口文档来开发后端的代码了。如果我们开发完了某个功能&#xff0c;后端如何验证我们开发的是否正确呢&#xff1f;我们就需要测试&#xff0c;使用Swagger就可以帮助后端生成接口文档&#xff0c;并且可以进行后端的接…...

从CL1看生物计算机的创新突破与发展前景:技术、应用与挑战的多维度剖析

一、引言 1.1 研究背景与意义 随着科技的飞速发展&#xff0c;计算机技术已经成为推动现代社会进步的核心力量之一。从最初的电子管计算机到如今的大规模集成电路计算机&#xff0c;计算机的性能得到了极大的提升&#xff0c;应用领域也不断拓展。然而&#xff0c;传统计算机…...

OpenCV视频解码性能优化十连击(实测帧率提升300%)

解密工业级视频处理优化方案&#xff01;从硬件加速到多线程榨干CPU/GPU性能&#xff0c;附RTSP流调优参数与内存泄漏排查技巧。 &#x1f527; 优化前准备 环境检测脚本 import cv2# 验证硬件加速支持 print("CUDA支持:", cv2.cuda.getCudaEnabledDeviceCount() &…...

springboot3 RestClient、HTTP 客户端区别

1 RestClient使用 RestClient 是 Spring 6.1 M2 中引入的同步 HTTP 客户端&#xff0c;它取代了 RestTemplate。同步 HTTP 客户端以阻塞方式发送和接收 HTTP 请求和响应&#xff0c;这意味着它会等待每个请求完成后才继续下一个请求。本文将带你了解 RestClient 的功能以及它与…...

智能手表不可插卡怎么用

一、连接蓝牙 智能手表一般都可以通过蓝牙连接手机&#xff0c;以实现一些基础功能。连接方式一般分为以下几步&#xff1a; 1、首先打开手机的蓝牙功能&#xff0c;并在蓝牙列表中搜索手表的设备名称。 2、找到手表的设备名称后&#xff0c;点击连接即可完成蓝牙连接。 3、…...

blender看不到导入的模型

参考&#xff1a;blender 快捷键 常见问题_blender材质预览快捷键-CSDN博客 方法一&#xff1a;视图-裁剪起点&#xff0c;设置一个很大的值 方法二&#xff1a;选中所有对象&#xff0c;对齐视图-视图对齐活动项-选择一个视图...

【Unity】 HTFramework框架(六十一)Project窗口文件夹锁定器

更新日期&#xff1a;2025年3月7日。 Github源码&#xff1a;[点我获取源码] Gitee源码&#xff1a;[点我获取源码] 索引 Project窗口文件夹锁定器框架文件夹锁定自定义文件夹锁定限制条件 Project窗口文件夹锁定器 在Project窗口中&#xff0c;文件夹锁定器能够为任何文件夹加…...

智能体开发:推理-行动(ReAct)思维链提示

人类在处理一个需要多个步骤才能完成任务时&#xff0c;显著特点是能够将言语推理&#xff08;内心独白&#xff09;和实际行动融合在一起&#xff0c;在面对陌生或不确定的情况时通过这种方法学习新知识&#xff0c;做出决策&#xff0c;并执行&#xff0c;从而应对复杂的任务…...

机试准备第11天

第一题是浮点数加法&#xff0c;目前写过最长的代码。 #include <stdio.h> #include <string> #include <iostream> #include <vector> using namespace std; int main() {string str1;string str2;while (getline(cin, str1) && getline(cin…...

【Proteus仿真】【STM32单片机】智能阳台控制系统

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真STM32单片机控制器&#xff0c;使用按键、LCD1604液晶、DHT11温湿度模块、PCF8591 ADC、光线传感器、PM2.5传感器、土壤湿度传感器、继电器、水泵、电灯、28BYJ48步进电机等。 主要…...

Manus AI Agent 技术解读:架构、机制与竞品对比

目录 1. Manus 是什么&#xff1f; 1.1 研发背景 1.2 技术特点 1.3 工具调用能力 1.4 主要应用场景 2. Manus 一夜爆火的原因何在&#xff1f; 2.1 技术突破带来的震撼 2.2 完整交付的产品体验 2.3 生态与开源策略 3. Manus 与其他 AI Agent 的对比分析 3.1 技术架构…...

【时间序列】因果推断:从时序数据中探寻“因”与“果”

在日常生活中&#xff0c;我们经常听到这样的问题&#xff1a;“为什么股票价格会突然下跌&#xff1f;”、“天气变化是否会影响销售额&#xff1f;”这些问题背后&#xff0c;其实都在试图寻找一种因果关系。然而&#xff0c;在时间序列数据中&#xff0c;探寻因果关系并不像…...

IDEA2023 使用枚举类型java: 非法字符: ‘\ufffd‘

一、异常&#xff1a; 二、原因 文件编码问题 IDE或文本编辑器的文件编码设置不正确&#xff0c;可能会导致在保存文件时引入了错误的字符。 三、解决 在IntelliJ IDEA中&#xff0c;你可以通过File -> Settings -> Editor -> File Encodings来设置。...

深度学习模型组件之优化器--基础优化器(GD、SGD、Mini-batch SGD)

深度学习模型组件之优化器–基础优化器&#xff08;GD、SGD、Mini-batch SGD&#xff09; 文章目录 深度学习模型组件之优化器--基础优化器&#xff08;GD、SGD、Mini-batch SGD&#xff09;1. 梯度下降&#xff08;Gradient Descent, GD&#xff09;1.1 基本原理1.2 优点与缺点…...

使用 AIStor、MLflow 和 KServe 将模型部署到 Kubernetes

在之前几篇关于 MLOps 工具的文章中&#xff0c;我展示了有多少流行的 MLOps 工具跟踪与模型训练实验相关的指标。我还展示了他们如何使用 MinIO 来存储作为模型训练管道一部分的非结构化数据。但是&#xff0c;一个好的 MLOps 工具应该做的不仅仅是管理您的实验、数据集和模型…...

宝塔 Linux 计划任务中添加运行项目网站PHP任务-定时任务

一、指定php版运行&#xff0c; cd /www/wwwroot/www.xxx.com/ && /www/server/php/56/bin/php think timedtasks start >> /tmp/timedtasks.log 2>&1 二、不指定php版 cd /www/wwwroot/www.xxx.com/ && php think timedtasks start >> …...

unity学习64,第3个小游戏:一个2D跑酷游戏

目录 学习参考 素材资源导入 1 创建项目 1.1 创建1个2D项目 1.2 导入素材 2 背景图bg 2.0 bg素材 2.1 创建背景 2.2 修改素材&#xff0c;且修改摄像机等 2.2.1 修改导入的原始prefab素材 2.2.2 对应调整摄像机 2.2.3 弄好背景 2.3 背景相关脚本实现 2.3.1 错误…...

rom定制系列------小米note3 原生安卓15 批量线刷 默认开启usb功能选项 插电自启等

小米Note 3搭载骁龙660处理器&#xff0c;1200万像素广角镜头、俗称大号版的小米6&#xff0c;官方最终版为12.0.1稳定版安卓9的固件。客户需要运行在安卓15的rom。根据原生官网的rom修改一些功能选项。以便客户操作需求。 定制资源说明 根据客户需求采用安卓15原生系统为底包…...