打开IDEA,程序员思考的永远只有两件事!!!

微信公众号:牛奶 Yoka 的小屋
有任何问题。欢迎来撩~
最近更新:2024/07/09

[大家好,我是牛奶。]

当年面试时背了很多八股文,但在日渐重复的机械工作中(产品业务开发),计算机网络、操作系统、算法等很多晦涩难懂的基础知识已在脑海日渐模糊,每天打开 IDEA,思考的永远只有两件事:

  • 新需求的代码怎么写?
  • 新 BUG 单在代码上怎么改?

这是程序员在工作中最核心的两件事。所以就想聊聊这两件事所带来的两个问题:

  • 怎样写好代码?
  • 怎样重构代码让 BUG 更少且性能更好?

最近闲来无事读了《代码整洁之道》和《重构》,刚好这两本书,一个提供规范,一个优化代码,所以这篇文章,我分享三个看似简单,实则陷阱重重甚至很多反直觉的代码规范和重构技巧,这也是我在日常工作中最常用的三个规范(如下图),愿对诸君有所帮助。

代码命名的学问

代码命名规范

命名的学问可远比我想象的大的多。最初以为命名不好无非不方便理解,多添加注释即可,现在想来太天真,命名不仅可能影响代码阅读,还可能影响代码优化甚至代码运行。下面介绍几个比较经典的命名问题,talk is cheap,上代码:

   public class ProgrammerSalaryCalculator {
    public static void main(String[] args) {
        int age = 30;
        boolean isReadCleanCodeBook = true;
        String p = "架构师";
        double salary = salary(age, isReadCleanCodeBook, p);
    }

  // 计算程序员薪水。
  // 规则如下:如果是25-35岁的程序员,且读过《代码整洁之道》和《重构》这两本书,平均月薪2万元;
  //如果是35-45岁程序员,如果岗位是架构师或管理,则薪资根据公司-薪资表获取。
    public static double salary(int age, boolean isReadCleanCodeBook, String p) {
        int result = 0;
        if (age >= 25 && age < 35&& isReadCleanCodeBook){
            return 20000;
        } else if (age >= 35 && age <= 45) {
            if ("架构师".equals(p) || "管理".equals(p)) {
                result =  salaryDAO.getSalaryInfo(age);
                return result;
            }
        } else {
            return 0;
        }
    }
}

这段代码有 5 处问题,诸位共发现几处?我们来一一识别一下:

1、**方法名称使用动词+名词表示。**有动词有名词,才能完整表示要做的事。比如只写名词basketball,很难根据名字判断出该方法是买篮球还是打篮球,但是命名为playBasketball便一目了然。『上述计算程序员薪水的方法命名,应优化为 calculateSalary。

2、**变量名称用含义明确的名词。**不要使用意义不明的一个字母作为变量;不要使用不通用的缩写作为变量;也不要使用数字结尾的无效命名作为变量;这一类的命名很难向读者表达这些变量的意图。『上述的p变量命名,应优化为position表示岗位的含义。

3、**布尔类型的变量都不要加is。**这条出自阿里的《Java开发手册》。核心原因是,一些用于远程调用的RPC框架,在对从远程过来的对象进行反序列化解析时,会将is开头的布尔类型属性字段解析成不带is的属性字段,因为如fastJson、jackson这些工具反序列化的机制是根据字段的get方法名获取,但在JavaBean规范中,如isSuccess和success两个属性的get方法都是isSuccess(),因此解析就会出错,这就是我上文所说命名影响代码运行。『上述表示是否读过整洁代码书籍的变量命名,应优化为ReadCleanCodeBook。

4、**区分不同层的增删改查命名。**基础设施层对数据库操作的增删改查,现在基本公认使用insertXxx、deleteXxx、updateXxx、selectXxx的方法命名;为了区分基础设施层,接口层、应用层、领域层一般使用createXxx,removeXxx,modifyXxx,getXxByYy的方式进行方法命名。当然命名根据个人喜好,只要容易加以区分即可。『上述根据公司-薪资表查询薪资的DAO层方法命名可优化为selectSalaryInfoByAge。

5、最后一点非命名问题,却和命名有关。Bob大叔在书里说:

“每次写注释,你都该做个鬼脸,感受自己在表达能力上的失败。”——Robert C. Martin

Bob大叔强调,**能用代码表示意图的地方就不要用注释。**注释越多,反而表明你代码的表达能力越弱。他倒是不排斥长命名,书里的很多案例的命名都挺长,看他的代码,你能明显感觉到为了让读者能看懂代码,各种命名真是煞费苦心,哈哈。注释还有一个弊端在于,我们更新大量代码逻辑后,往往不会同步更新注释,当较多的注释和代码逻辑不一致时,就会给后续代码理解造成误解。当然,有些注释不能删,比如版权注释,比如一些实在晦涩难懂的逻辑等。

除以上几个关键的命名问题,还有包名小写,类名首字母大写;在接口类前面不要加一个I前缀,因为它是C# 的习惯(这个有些反直觉);集合类变命名展示出key和value的集合含义等。这些相对容易理解,这里就不展开分析了。

代码命名优化

修改变量名需要全局修改,修改前先使用快捷键 crtl+shift+F10 跑一下测试用例,确保功能正常。shift+F6 全局修改命名,修改完成后再次跑一下测试用例,确保优化无误。优化后正确代码如下:

public class ProgrammerSalaryCalculator {
    public static void main(String[] args) {
        int age = 30;
        boolean readCleanCodeBook = true;
        String position = "架构师";
        double salary = calculateSalary(age, readCleanCodeBook, position);
    }

    public static double calculateSalary(int age, boolean isReadCleanCodeBook, String position) {
        int result;
        if (age >= 25 && age < 35&&isReadCleanCodeBook){
            return 20000;
        } else if (age >= 35 && age <= 45) {
            if ("架构师".equals(position) || "管理".equals(position)) {  
                return salaryDAO.SelectSalaryInfo(age);
            }
        } else {
            return 0;
        }
    }
}

代码重复

“在简单代码规则中,我最在意代码重复。如果同一段代码反复出现,就表示某种想法未在代码中得到良好的体现。”——Robert C. Martin

代码重复是大佬最重视的一点。像我这种菜鸟,最开始以为重复代码可以一眼识别,IDEA也有辅助工具提示代码重复,没有多重要,too young too simple。诸君且看,重复代码共分为三类:

  • 同一类中的代码重复
  • 互为兄弟的子类间代码重复
  • 不同类间的代码重复

我们常见第一类,但第二三类重复也同样重要,且较为隐蔽。由于我们很多系统开发都是多人协作。很难避免不会出现不同类间存在重复代码。所以,这里针对三类重复代码提供一些优化方式:

同一类中的代码重复

这类处理最简单。直接将两个方法合并为一个方法。IDEA提供了快捷键的方式,**选中重复代码块,按下 Crtl+Alt+M,IDEA就会自动识别重复代码块并抽取公共方法,之后给这个方法命名即可。**当然,在修改代码前后,别忘了 crtl+shift+F10 跑一下测试用例,确保重构前后代码逻辑没有发生实质变化。具体操作过程如下:

具体视频地址

互为兄弟的子类间代码重复

两个兄弟类中代码重复,我们第一时间就是想办法把重复代码提到父类中。怎么提呢?

  1. 先利用Crtl+Alt+M快捷键把重复代码抽取为方法。

  2. 使用快捷键Crtl+Alt+Shift+T->Pull Members up(有些版本IDEA需要去Refactor中去找Pull Members up)将重复方法上移父类。

  3. 将另一个类中重复代码块替换为父类对应方法。

同理,上述每一步对代码的改动都需要crtl+shift+F10 运行相应测试用例,保证代码逻辑无改动。

具体演示如下,该案例直接将两个方法合并至父类:

具体视频地址

不同类间的代码重复

这种最复杂,不过和上一类重复大差不差。只不过将重复方法提取到新类中:

  1. 先利用Crtl+Alt+M快捷键把重复代码抽取为方法。

  2. 再通过Crtl+Alt+Shift+T->Extract Delegate抽取为新类+方法

  3. 将另一个类中重复代码块替换为新类对应方法。

具体操作如下:
具体视频地址

最后,并非所有的重复都需要消除。多微服务间的数据模型、模型转换、client连接、以及完全不相干业务中极少量的逻辑业务重复等,不需要消除重复。过度的消除重复可能会导致代码太过耦合,是否需要消除重复还是需要视具体的业务场景来定。

视频中所使用的快捷键如下:

快捷键含义
crtl+shift+F10跑该类对应的测试用例
Crtl+Alt+M重复代码抽取公共方法
Crtl+Alt+Shift+T->Pull Members up将方法上移到父类中
Crtl+Alt+Shift+T->Extract Delegate将方法提取到一个新/旧类中

视频中对应的代码:

public class Main {
public static void main(String[] args) {
calculateChenGuangMarketPrice("apple", 1);
calculateDaShanMarketPrice("apple", 1);
      System.out.println("Hello world!");
  }

public static Double calculateChenGuangMarketPrice(String type, Integer number) {
      Double prices;
switch(type) {
case "Orange":
              prices = 3.0;
break;
case "apple":
              prices = 5.0;
break;
default:
throw new IllegalArgumentException("error type:" + type);
      }
return prices * number;
  }

public static Double calculateDaShanMarketPrice(String type, Integer number) {
      Double prices;
switch(type) {
case "Orange":
              prices = 3.0;
break;
case "apple":
              prices = 5.0;
break;
default:
throw new IllegalArgumentException("error type:" + type);
      }
return prices * number;
  }
} 

测试代码:

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class MarketTest {
@InjectMocks
private Market market;

@Test
public void calculateChenGuangMarketPriceTest() {
      String type = "apple";
      Integer number = 2;
      Double expected = 10.0;
      Assert.assertEquals(expected, market.calculateChenGuangMarketPrice(type, number));
  }

@Test
public void calculateDaShanMarketPriceTest() {
      String type = "apple";
      Integer number = 2;
      Double expected = 10.0;
      Assert.assertEquals(expected, market.calculateDaShanMarketPrice(type, number));
  }
}

“消除重复和提高表达力让我在整洁代码方面获益良多,只要铭记这两点,改进脏代码时就会大有不同。”——Robert C. Martin

合格的方法

类中的方法编码时,针对入参、方法实现、出参,有三个在实际开发中常用的规范需要注意:

  • 方法入参不要超过5个
  • 方法行数不超过50行
  • 方法出参不要返回null

针对每一点,咱们都展开来说说。

方法入参优化

方法入参不要超过5个。超过5个我们就要想办法简化。我们常见的优化手法一般是参数合并法,比如针对多个入参是从同一数据结构中抽取,直接传递该数据结构作为入参;如果几项关联参数总是同时出现,将这几个关联参数整合为对象参数传递;在《重构》一书中提出的另外三种优化建议,我觉更应该引起重视:

  • 移除标记参数
  • 以查询取代参数
  • 函数组合成类
移除标记参数

对于标记参数,我真是深受其害,我曾在实际开发过程中看到两行代码,调用了一个方法四次进行条件判断,这个方法的后两个参数是布尔类型,调四次就是对这两个布尔类型入参的四种组合。每次看到这里,我都要去思考下这四种入参分别是执行方法中的哪一个逻辑,阅读非常吃力。在《重构》一书第11章第3节强调:

“我不喜欢标记参数,因为它们让人难以理解到底有哪些函数可以调用、应该怎么调用。拿到一份 API 以后,我首先看到的是一系列可供调用的函数,但标记参数却隐藏了函数调用中存在的差异性。使用这样的函数,我还得弄清标记参数有哪些可用的值。布尔型的标记尤其糟糕,因为它们不能清晰地传达其含义——在调用一个函数时,我很难弄清 true 到底是什么意思。如果明确用一个函数来完成一项单独的任务,其含义会清晰得多。——Martin Fowler

这里的标记参数具体是指调用者用它来指示被调函数应该执行哪一部分逻辑的参数。并非只有布尔类型是标记参数,举个非布尔类型标记参数案例:

    public Integer setDimension (String name, String value) {
      int res = 0;
      if (Objects.equals(name, "height")) {
          this.height = value;
          res = 1;
          return res;
      }
      if (Objects.equals(name, "width")) {
          this.width = value;
          res = 2;
          return res;
      }
      return res;
  }

优化后为:

public Integer setHeight (String value) {
      this.height = value;
      return 1;
  }
  public Integer setwidth (String value) {
      this.width = value;
      return 2;
  }

一个方法中,存在多个处理逻辑,本身就违背单一职责原则(SRP),所以针对标记参数,强烈建议使用正确的命名拆分该方法。

以查询取代参数

我们写的接口,除了给前端提供,很多时候需要对外部系统提供,这个时候,如果一个参数我们可以自己获取,就不要再让外部来传参了。不然联调接口的时候会出现很多麻烦事。调用方可能参数传错,可能参数漏传,可能要求非必填等等。重构的作者也强调:

“如果调用函数时传入了一个值,而这个值由函数自己来获得也是同样容易,这就是重复。这个本不必要的参数会增加调用者的难度,因为它不得不找出正确的参数值,其实原本调用者是不需要费这个力气的。
——Martin Fowler

函数组合成类

这一点不是很好理解。看下图,两个方法,转变为类中的两个方法。同时,这两个方法的参数没了。我觉得这个重构手段更名为**“参数消失术”**还更好理解点。


这样做的原因在于,两个方法参数相同,且这两个方法总是和其参数同时出现,我们便将关联性较强的功能和数据放到一个类中。而类本身的定义为:**具有相同特性(数据元素)和行为(功能)的对象的抽象就是类。**因此,我们不过就是从参数的角度,对数据和行为做了一次抽象。《重构》的作者认为:

如果发现一组函数形影不离地操作同一块数据(通常是将这块数据作为参数传递给函数),我就认为,是时候组建一个类了。类能明确地给这些函数提供一个共用的环境,在对象内部调用这些函数可以少传许多参数,从而简化函数调用,并且这样一个对象也可以更方便地传递给系统的其他部分。——Martin Fowler

方法内容优化

我第一次优化代码,做的第一件事,便是把我写的好几处代码提取为各自的方法。在这之前,我本能的认为,一个方法里面调用好多方法,是一种不规范的行为。没想到不论是Robert C. Martin还是Martin Fowler大佬,都非常支持小函数。他们指出,**活的最长、最好的程序,其中的函数都比较短。**看到这句话,彻底打破我之前的编码风格。不过,针对方法/函数的抽取也不能太过随意,应尽可能的将业务逻辑从上往下依次抽象出方法。用比如打印发票举个例子,我绘制了一个打印发票的思维导图(如下图),在我看来,从左往右,每个分支便可抽象出一个方法,所有的业务逻辑都可以在思维导图中逐层拆解最后转换为包含一层层方法的代码

另外,Martin Fowler也给出提取方法的时机:

每当感觉需要以注释来说明点什么的时候,我们就把需要说明的东西写进一个独立函数中,并以其用途(而非实现手法)命名。——Martin Fowler

当我们习惯不断递归的抽象出方法进行开发,那一般方法行数基本不会超过50行。

方法出参优化

我写代码时,最烦的一件事,便是对接口返回的数据进行判空处理。几乎任何一个接口返回,都需要进行判空。虽然很烦,又不得不做。不然你不知道什么情况下就会出现空指针异常。Bob大叔建议,如果你想返回null值,不如抛出异常,或者返回特例对象。举个例子:

  List<Employee> employees = getEmployees();
if (employees != null) {
  for(Employee e : employees) {
    totalPay += e.getPay();
  }
}

像上述这种判空,如果getEmployees方法直接返回空集合Collections.emptyList(),则完全可以避免判空操作:

List<Employee> employees = getEmployees();
for(Employee e : employees) {
totalPay += e.getPay();
}

因此,出参为集合的接口返回,如果为空,建议一律返回 java.util.Collections.emptyList/emptyMap/emptyXXX等自带的空集合。

后记

编码的问题其实非常多,除这三个代码规范,还包括为提高代码健壮性对线程池、序列化/反序列化的规范;为防止OOM对接口返回大对象的规范,对循环调用RPC的规范;为保证数据库事务问题对事务注解的规范;为防止随意打印日志对日志框架和日志级别的规范等。
我这里指出的代码规范和重构技巧仅仅九牛一毛,想要写出好的代码,还需要多写多练,提高基本功,总结出自己的优秀编码习惯。

愿我们每位开发者不断提高编码能力,此生再无BUG!!!

----------------end----------------
我是牛奶,目前是一名互联网开发菜鸟,主要聚焦于互联网技术开发和个人成长的高营养价值内容分享,感兴趣的小伙伴可以在下方加个关注,大家一起共同学习和进步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/787123.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

leetcode:LCR 018. 验证回文串(python3解法)

难度&#xff1a;简单 给定一个字符串 s &#xff0c;验证 s 是否是 回文串 &#xff0c;只考虑字母和数字字符&#xff0c;可以忽略字母的大小写。 本题中&#xff0c;将空字符串定义为有效的 回文串 。 示例 1: 输入: s "A man, a plan, a canal: Panama" 输出: t…

编辑器 goland 和 visual studio code

goland 编辑器做的真是太好了&#xff0c;面向 go 代码的定制设计&#xff0c;但它是收费软件&#xff0c;价格还贵的超出了自己的经济能力范围。有时候想打几行代码&#xff0c;却没有趁手的兵器&#xff0c;真是难受。但求助免费破解版吧&#xff0c;又需要关注公众号&#x…

Lab1 论文 MapReduce

目录 &#x1f339;前言 &#x1f985;2 Programming Model &#x1f33c;2.1 Example &#x1f33c;2.2 Types &#x1f33c;2.3 More Examples &#x1f985;3 Implementation(实现) &#x1f33c;3.1 ~ 3.3 &#x1f33c;3.4 ~ 3.6 &#x1f985;4 Refinemen…

Java-Redis-Clickhouse-Jenkins-MybatisPlus-Zookeeper-vscode-Docker-jdbc-xxljob

文章目录 Clickhouse基础实操windows docker desktop 下载clickhousespringboot项目配置clickhouse Redis谈下你对Redis的了解&#xff1f;Redis一般都有哪些使用的场景&#xff1f;Redis有哪些常见的功能&#xff1f;Redis支持的数据类型有哪些&#xff1f;Redis为什么这么快…

爬虫怎么实现抓取的

1.4爬虫工程师常用的库通过图1-3我们了解到&#xff0c;爬虫程序的完整链条包括整理需求、分析目标、发出网络请求、文本解析、数据入库和数据出库。其中与代码紧密相关的有&#xff1a;发出网络请求、文本解析、数据入库和数据出库&#xff0c;接下来我们将学习不同阶段中爬虫…

Proxmox VE 8虚拟机直通USB磁盘

作者&#xff1a;田逸&#xff08;fromyz&#xff09; 今天有个兄弟发消息&#xff0c;咨询怎么让插在服务器上的U盾被Proxmox VE上的虚拟机识别。在很久很久以前&#xff0c;我尝试过在Proxmox VE 5以前的版本创建windows虚拟机&#xff0c;并把插在Proxmox VE宿主机上的银行U…

[ TOOLS ] JFLASH 使用说明

一、使用everything查找JFLASH everything是指这个软件&#xff0c;使用这个方便查找想要的文件 二、创建一个工程并配置 创建完后进行配置&#xff1a; Target devic: 板子的芯片型号&#xff0c;比如R7FA6M4Target interface: 一般是SWDSpeed: 一般是4000kHz, 不能下载则将Sp…

快速将一个网址打包成一个exe可执行文件

一、电脑需要node环境 如果没有下面有安装教程&#xff1a; node.js安装及环境配置超详细教程【Windows系统安装包方式】 https://blog.csdn.net/weixin_44893902/article/details/121788104 我的版本是v16.13.1 二、安装nativefier 这是一个GitHub上的开源项目&#xff1a…

ROS2 分布式 及 ssh远程控制 和 上传下载文件或文件夹

问题1. 多台计算机连接同一wifi后 &#xff0c;运行ROS2的小乌龟案例&#xff0c;自己的计算机&#xff0c;无法控制其他电脑的小乌龟 按照正常的情况来说&#xff0c;ROS2是DDS的自发现通信机制&#xff0c;只要处在同一wifi网络中&#xff0c; A计算机执行启动小乌龟的命…

PHP验证日本免费电话号码格式

首先&#xff0c;您需要了解免费电话号码的格式。 日本免费电话也就那么几个号段&#xff1a;0120、0990、0180、0570、0800等开头的&#xff0c;0800稍微特殊点&#xff0c;在手机号里面有080 开头&#xff0c;但是后面不一样了。 关于免费电话号码的划分&#xff0c;全部写…

2024-07-09 Linux 使用gpio-keyboard标准方式获取按键事件实例代码

一、kernel dts 配置修改&#xff1a; diff --git a/sysdrv/source/kernel/arch/arm/boot/dts/rv1106g-evb1-v11.dts b/sysdrv/source/kernel/arch/arm/boot/dts/rv1106g-evb1-v11.dts index d0d059a3b..584f3a00a 100755 --- a/sysdrv/source/kernel/arch/arm/boot/dts/rv110…

【效率提升】多功能组织和整理软件一Notion

Notion下载地址&#xff1a;https://www.notion.so/desktop Notion 是一款多功能办公软件&#xff0c;非常适合进行知识整理、团队协作、项目整理等。 下面是几个我推荐Notion的关键点&#xff1a; 一、排版高度自由&#xff1a;Notion的页面可以嵌套&#xff0c;在页面中还支…

关于腾讯的那些事(6月新闻纪要)

祝贺&#xff01;深圳市科技进步一等奖 这份文件是关于腾讯云数据库TDSQL获得深圳市科技进步一等奖的详细报道。以下是详细总结分析&#xff1a; 获奖荣誉&#xff1a; 腾讯云数据库TDSQL荣获2022年深圳市科技进步一等奖&#xff0c;成为唯一入选的数据库产品。该奖项由深圳市…

213.贪心算法:跳跃游戏||(力扣)

class Solution { public:int jump(vector<int>& nums) {if (nums.size() 1) return 0; // 如果数组长度为1&#xff0c;已经在终点&#xff0c;不需要跳跃int cur 0; // 当前跳跃能到达的最远位置int flag 0; // 记录跳跃次数int next 0; // 下一次跳跃能到…

JavaScript 闭包

目录 一、前言 二、JavaScript 变量作用域 1、变量作用域 2、如何从函数外部访问内部变量 三、JavaScript 闭包 1、闭包的定义 2、闭包的组成 3、实例说明 四、闭包的优缺点 1、优点 2、缺点 五、一个有趣的实例&#xff08;定时器与闭包&#xff09; 一、前言 先…

OpenCV对图片中的水果进行识别计算其面积长度等

本项目所用到的技术有&#xff1a; OpenCV Python的一些库&#xff1a;sys,openpyxl,numpy,PyQt5,PIL 本文可以做一些课程设计的项目 本文为作者原创&#xff0c;转载请注明出处&#xff0c;如果需要完整的代码&#xff0c;可以关注我私信 上面是用到的样例图片&#xff0c;一张…

如何在OpenFOAM的案例文件夹中确定数据的点和面,确定点和网格之间的关系,从而用于深度学习预测和构建模型呢(分析数据格式及其含义)

在OpenFOAM中&#xff0c;点&#xff08;points&#xff09;和面&#xff08;faces&#xff09;的定义是通过不同的文件来进行的。在案例一级目录下面的constant/polyMesh目录下&#xff0c;会有points, faces, owner, neighbour等文件&#xff0c;来描述网格的几何和拓扑结构。…

最新深度技术Win7精简版系统:免费下载!

在Win7电脑操作中&#xff0c;用户想要给电脑安装上深度技术Win7精简版系统&#xff0c;但不知道去哪里才能找到该系统版本&#xff1f;接下来系统之家小编给大家带来了深度技术Win7系统精简版本的下载地址&#xff0c;方便大家点击下载安装。系统安装步骤已简化&#xff0c;新…

数据解读加密世界的重新定位:全球流动性困境下的转型之痛

全球每一天将会产生50亿次以上的搜索&#xff0c;每一天有491EB的数据出现在我们的生活中&#xff0c;如果这些数据量全部以Email的形式展现&#xff0c;那相当于1个人1天需要处理36亿封电子邮件。随着区块链技术的不断发展&#xff0c;从链下到链上&#xff0c;链上数据构建的…

SVM - 径向基函数核 Radial Basis Function Kernel,简称RBF核或者高斯核

SVM - 径向基函数核 Radial Basis Function Kernel&#xff0c;简称RBF核或者高斯核 flyfish 径向基函数核&#xff08;Radial Basis Function Kernel&#xff0c;简称RBF核&#xff09;&#xff0c;也称为高斯核&#xff0c;是一种常用的核函数&#xff0c;用于支持向量机&a…