04.仿简道云公式函数实战-QLExpress基础语法

1. 前言

小伙伴大家好,在上一篇文章我们简单初探了QLExpress表达式引擎,我们简单写了一个HelloWorld的程序,并成功的运行期望的结果。在本篇文章中我们来熟悉一下QLExpress的语法,因为我们在后面简道云公式实战的时候,需要用到这些语法。废话少说,直接开始。

2. 基础语法

相信大家也下载了QLExpress的源码,在下载的源码中有一个readme文件,在这个文件中,源码作者已经介绍了语法以及QLExpress的用法。大家可以详细阅读,以及运行相应的测试文件。如图所示:

2.1 操作符和java对象

2.1.1 操作符

在readme说明文件中,我们知道QLExpress支持的操作符有:

+,-,*,/,<,>,<=,>=,==,!=,<>,%,++,–-
in 【类似sql】,like【sql语法】,&&,|| 
支持for,break、continue、if then else 等标准的程序控制逻辑

上述的的操作符,笔者都会写测试用例。我们先从简单的四则运算开始:

2.1.1.1 四则运算

四则运算需求提出:
需求1:编写java程序使用QLExpress表达式引擎,计算"1+2-3*4/5" 表达式的结果,并在控制台打印结果
需求2:编写java程序使用QLExpress表达式引擎,计算"1 加 2 减 3 乘 4 除 5"表达式的结果,并在控制台打印结果

当我们拿到需求的时候,首先第一步我们要明确需求,需求是让我们借助QLExpress表达式引擎,来计算表达式的结果。

表达式中包括英文"+-*/"和中文"加 减 乘 除"。需求中并没有提出计算结果精度的问题(虽然需求没有定下来,我们要支持高精度计算)。

基于上述的讨论后,码农就拿起键盘一头扎进了QLExpress代码学习中,以及各种百度,CSDN搜索解决方案。最终码农A编写了需求1如下代码:

/**** "1+2-3*4/5"*/
@Test
public void test1() throws Exception{// @param isPrecise 是否需要高精度计算支持// @param isTrace   是否跟踪执行指令的过程ExpressRunner runner = new ExpressRunner(true, true);String expressStr = "1+2-3*4/5";// isTraceobject rst = runner.execute(expressStr, null, null, true, true);System.out.println(rst);
}

码农A很自豪的讲起了自己的解决方案,QLExpress引擎提供了isPrecise 和 isTrace两个属性,在ExpressRunner 初始化的时候可以指定isPrecise 是否需要高精度计算支持和isTrace 是否跟踪执行指令的过程。isTrace在调试阶段很有用,可以查看表达式执行指令的整个过程,在程序上线时,建议设置为false避免浪费资源。

如果isPrecise=true代码运行的结果为0.6000000000;如果isPrecise = false代码运行结果为1.代码运行如图所示:

码农A沮丧的说,我解决了需求1,但是需求2没有找到解决方案。项目组中有人找到需求2的解决方案吗?大家可以交流一下。一向低调的码农B开口了。

码农B说:通过阅读QLExpress代码,找到一个方法

addOperatorWithAlias("加","+",null)。

/*** 添加操作符和关键字的别名,同时对操作符可以指定错误信息。* 例如:addOperatorWithAlias("加","+",null)** @param keyWordName* @param realKeyWordName* @param errorInfo* @throws Exception*/
public void addOperatorWithAlias(String keyWordName, String realKeyWordName, String errorInfo) throws Exception {if (errorInfo != null && errorInfo.trim().length() == 0) {errorInfo = null;}//添加函数别名if (this.manager.isFunction(realKeyWordName)) {this.manager.addFunctionName(keyWordName);this.operatorManager.addOperatorWithAlias(keyWordName, realKeyWordName, errorInfo);return;}NodeType realNodeType = this.manager.findNodeType(realKeyWordName);if (realNodeType == null) {throw new QLException("关键字:" + realKeyWordName + "不存在");}boolean isExist = this.operatorManager.isExistOperator(realNodeType.getName());if (!isExist && errorInfo != null) {throw new QLException("关键字:" + realKeyWordName + "是通过指令来实现的,不能设置错误的提示信息,errorInfo 必须是 null");}if (!isExist || errorInfo == null) {//不需要新增操作符号,只需要建立一个关键子即可this.manager.addOperatorWithRealNodeType(keyWordName, realNodeType.getName());} else {this.manager.addOperatorWithLevelOfReference(keyWordName, realNodeType.getName());this.operatorManager.addOperatorWithAlias(keyWordName, realNodeType.getName(), errorInfo);}
}

此方法作用就是添加操作符和关键字的别名,于是就构思出来如下代码【test2方法运行报错】

@Test
public void test2() throws Exception{ExpressRunner runner = new ExpressRunner(true, true);String expressStr = "1 加 2 减 3 乘 4 除 5";runner.addOperatorWithAlias("加","+","加 的这个操作符有问题");runner.addOperatorWithAlias("减","-","减 的这个操作符有问题");runner.addOperatorWithAlias("乘","*","乘 的这个操作符有问题");runner.addOperatorWithAlias("除","/","除 的这个操作符有问题");// isTraceobject rst = runner.execute(expressStr, null, null, true, true);System.out.println(rst);
}

经测试发现程序报错:

com.ql.util.express.exception.QLException: * 不能被设置别名:com.ql.util.express.instruction.op.OperatorMultiplyDivide.<init>(java.lang.String, java.lang.String, java.lang.String) 如下图所示:

通过报错信息可知OperatorMultiplyDivide.<init>方法有问题,于是就进入OperatorMultiplyDivide源码,模仿着写了

OperatorMultiply 类和 OperatorDivide类,即把 OperatorMultiplyDivide类拆分成两个类。

/*** 类描述:乘操作** @author admin* @version 1.0.0* @date 2023/11/13 17:17*/
public class OperatorMultiply extends Operator {@Overridepublic object executeInner(object[] list) throws Exception {return executeInner(list[0], list[1]);}public object executeInner(object op1, object op2) throws Exception {object result = OperatorOfNumber.multiply(op1, op2, this.isPrecise);return result;}}/*** 类描述:除操作** @author admin* @version 1.0.0* @date 2023/11/13 17:21*/
public class OperatorDivide extends Operator {@Overridepublic object executeInner(object[] list) throws Exception {return executeInner(list[0], list[1]);}public object executeInner(object op1, object op2) throws Exception {object result = OperatorOfNumber.divide(op1, op2, this.isPrecise);return result;}}

基于上面两个类,又写了test3方法(该方法运行报错)

@Test
public void test3() throws Exception{ExpressRunner runner = new ExpressRunner(true, true);String expressStr = "1 加 2 减 3 乘 4 除 5";runner.addOperator("*",new OperatorMultiply());runner.addOperator("/",new OperatorDivide());runner.addOperatorWithAlias("加","+","加 的这个操作符有问题");runner.addOperatorWithAlias("减","-","减 的这个操作符有问题");runner.addOperatorWithAlias("乘","*","乘 的这个操作符有问题");runner.addOperatorWithAlias("除","/","除 的这个操作符有问题");// isTraceobject rst = runner.execute(expressStr, null, null, true, true);System.out.println(rst);
}

运行报错:java.lang.RuntimeException: 节点类型定义重复:* 定义1=*:TYPE=KEYWORD 定义2=*:TYPE=KEYWORD

根据错误信息猜测应该是runner.addOperator("*",new OperatorMultiply());源码中已经有了,于是就找到OperatorFactory工厂类(笔者删减了其他代码)发现确实在这个工厂类中已经添加addOperator("*", new OperatorMultiplyDivide("*"));addOperator("/", new OperatorMultiplyDivide("/"));

public OperatorFactory(boolean isPrecise) {this.isPrecise = isPrecise;addOperator("!", new OperatorNot("!"));addOperator("*", new OperatorMultiplyDivide("*"));addOperator("/", new OperatorMultiplyDivide("/"));
}

既然有了那我就直接用汉字 不就能满足需求了,于是就又写了以下代码test4(运行通过)

@Test
public void test4() throws Exception{ExpressRunner runner = new ExpressRunner(true, true);String expressStr = "1 加 2 减 3 乘 4 除 5";runner.addOperator("乘",new OperatorMultiply());runner.addOperator("除",new OperatorDivide());runner.addOperatorWithAlias("加","+","加 的这个操作符有问题");runner.addOperatorWithAlias("减","-","减 的这个操作符有问题");// isTraceobject rst = runner.execute(expressStr, null, null, true, true);System.out.println(rst);
}

如果isPrecise=true代码运行的结果为0.6000000000;如果isPrecise = false代码运行结果为1

2.1.1.2 其余操作符测试案例

取余操作

/**** 测试操作符mod* isTrace:输出脚本的编译解析过程,一般对于业务系统来说关闭之后会提高性能。*/
@Test
public void mod() throws Exception{ExpressRunner runner = new ExpressRunner(false, true);String expressStr = "20 % 5";// isTraceObject rst = runner.execute(expressStr, null, null, true, true);System.out.println(rst);
}

加加操作

注意:++这个操作,分为前加加和后加加 如i++ 和++i,在QLExpress中前加加会报错。

/**** 测试++* @throws Exception*/
@Test
public void addPlusAfter() throws Exception{ExpressRunner runner = new ExpressRunner(false, true);DefaultContext<String, Object> context = new DefaultContext<>();context.put("a",11);context.put("b",12);String expressStr = "a++";// isTraceObject rst = runner.execute(expressStr, context, null, true, true);// 打印此时a的值是多少Object a_now = context.get("a");System.out.println(a_now);System.out.println(rst);
}/**** 测试++ 反例* @throws Exception com.ql.util.express.exception.QLCompileException: 程序错误,不满足语法规范,没有匹配到合适的语法,最大匹配致[0:-1]*/
@Test
public void addPlusBefore() throws Exception{ExpressRunner runner = new ExpressRunner(false, true);DefaultContext<String, Object> context = new DefaultContext<>();context.put("a",11);context.put("b",12);String expressStr = "++a";// isTraceObject rst = runner.execute(expressStr, context, null, true, true);// 打印此时a的值是多少Object a_now = context.get("a");System.out.println(a_now);System.out.println(rst);
}

减减操作

注意:--这个操作,分为前减减和后减减 如i-- 和--i,在QLExpress中前减减会报错。

/**** 测试--* @throws Exception*/
@Test
public void minusPlusAfter() throws Exception{ExpressRunner runner = new ExpressRunner(false, true);DefaultContext<String, Object> context = new DefaultContext<>();context.put("a",11);context.put("b",12);String expressStr = "a--";// isTraceObject rst = runner.execute(expressStr, context, null, true, true);// 打印此时a的值是多少Object a_now = context.get("a");System.out.println(a_now);System.out.println(rst);
}/**** 测试-- 反例* @throws Exception com.ql.util.express.exception.QLCompileException: 程序错误,不满足语法规范,没有匹配到合适的语法,最大匹配致[0:-1]*/
@Test
public void minusPlusBefore() throws Exception{ExpressRunner runner = new ExpressRunner(false, true);DefaultContext<String, Object> context = new DefaultContext<>();context.put("a",11);context.put("b",12);String expressStr = "--a";// isTraceObject rst = runner.execute(expressStr, context, null, true, true);// 打印此时a的值是多少Object a_now = context.get("a");System.out.println(a_now);System.out.println(rst);
}

不等于操作符

注意:不等于符号是 != 切记不要使用<>

/**** 测试 != 符号* @throws Exception*/
@Test
public void ne() throws Exception{ExpressRunner runner = new ExpressRunner(false, true);String expressStr = "20 != 5";// isTraceObject rst = runner.execute(expressStr, null, null, true, true);System.out.println(rst);
}/**** 测试 <> 符号 反例* @throws Exception com.ql.util.express.exception.QLCompileException: 程序错误,不满足语法规范,没有匹配到合适的语法,最大匹配致[0:1]*/
@Test
public void ne2() throws Exception{ExpressRunner runner = new ExpressRunner(false, true);DefaultContext<String, Object> context = new DefaultContext<>();context.put("a",11);context.put("b",12);String expressStr = "a <> b";// isTraceObject rst = runner.execute(expressStr, null, null, true, true);System.out.println(rst);
}

in操作

/**** in 测试*/
@Test
public void in() throws Exception{ExpressRunner runner = new ExpressRunner(false, false);String expressStr = " 3+4 in (8+3,7,9)";Object rst = runner.execute(expressStr, null, null, true, false);System.out.println(rst);
}

like操作

注意 ab如果作为一个值的话要用引号包裹,否则QLExpress会把ab当做一个变量

/**** like测试*/
@Test
public void like() throws Exception{// 注意ab必须用字符串包裹,不然会把ab当做变量ExpressRunner runner = new ExpressRunner(false, false);String expressStr = "'ab' like '%a%'";Object rst = runner.execute(expressStr, null, null, true, false);System.out.println(rst);
}

&&操作

/**** &&* @throws Exception*/
@Test
public void and() throws Exception{ExpressRunner runner = new ExpressRunner(false, false);String expressStr = "false && true";Object rst = runner.execute(expressStr, null, null, true, false);System.out.println(rst);}

||操作

/**** ||* @throws Exception*/
@Test
public void or() throws Exception{ExpressRunner runner = new ExpressRunner(false, false);String expressStr = "false || true";Object rst = runner.execute(expressStr, null, null, true, false);System.out.println(rst);}

三目表达式测试

/**** 测试三目表达式*/
@Test
public void san() throws Exception{ExpressRunner runner = new ExpressRunner(false, false);String expressStr = "int a=1;int b=2;a>b?a:b;";Object rst = runner.execute(expressStr, null, null, true, false);System.out.println(rst);
}

for 循环操作

注意:while循环测试报错

/**** 测试循环* @throws Exception*/
@Test
public void loop() throws Exception{ExpressRunner runner = new ExpressRunner(false, false);String expressStr = "int sum=10;"+ "for(int i = 0; i < 1; i = i + 1){"+ "    println(i); sum=sum+i;"+ "}" +"return sum";// isTraceObject rst = runner.execute(expressStr, null, null, true, false);System.out.println(rst);System.out.println("--------------java for loop------------");int sum=10;for (int i=0;i<1;i+=1) {System.out.println(i);sum = sum + i;}System.out.println(sum);
}/**** while 循环* @throws Exception*/
@Test
public void loop2() throws Exception {ExpressRunner runner = new ExpressRunner(false, true);String expressStr ="while(true) {println('1')}";Object rst = runner.execute(expressStr, null, null, true, false);System.out.println(rst);
}

if_then_else操作符

/**** if_then_else 测试*/
@Test
public void if_then_else() throws Exception{ExpressRunner runner = new ExpressRunner(false, false);String expressStr = "if 1==1 then {return 10}else{return 100}";Object rst = runner.execute(expressStr, null, null, true, false);System.out.println(rst);
}@Test
public void if_() throws Exception{ExpressRunner runner = new ExpressRunner(false, false);String expressStr = "if(1==1) { return 100;}";Object rst = runner.execute(expressStr, null, null, true, false);System.out.println(rst);
}@Test
public void if_else() throws Exception{ExpressRunner runner = new ExpressRunner(false, false);String expressStr = "if(1==2) { return 100;} else {" +"return -1;}";Object rst = runner.execute(expressStr, null, null, true, false);System.out.println(rst);
}@Test
public void if_then() throws Exception{ExpressRunner runner = new ExpressRunner(false, false);String expressStr = "if(1==1) then{ return 100;}";Object rst = runner.execute(expressStr, null, null, true, false);System.out.println(rst);
}

2.1.1.3 java对象操作

在QLExpress表达式引擎中,是支持操作java对象的,比如我们在一个表达式中需要调用一个java对象的方法作为处理的函数。下面我们还是通过测试用例,来说明java对象操作的知识点

1. 首先创建Bean对象

/*** 类描述:** @author admin* @version 1.0.0* @date 2023/11/13 16:03*/
public class Student {// 学号private String sn;// 姓名private String name;// 年龄private int age;public Student(){}public Student(String sn, String name, int age) {this.sn = sn;this.name = name;this.age = age;}public String getSn() {return sn;}public void setSn(String sn) {this.sn = sn;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public static String print(String msg) {String rst = "Student print method exe::::::"+msg;return rst;}
}

2.我们都知道java对象的生命周期是从初始化开始的,那么我们就用QLExpress表达式的形式初始化一个对象

/**** 测试java对象,测试创建对象*/
@Test
public void obj_init() throws Exception{ExpressRunner runner = new ExpressRunner(false, false);String expressStr = "import com.ql.util.express.self.base.Student; Student stu = new Student('000','tom',18); return stu.getName()";Object rst = runner.execute(expressStr, null, null, true, false);System.out.println(rst);
}

通过表达式我们可知:QLExpress是支持import的关键字

3.测试调用Student对象的print方法

/**** 测试调用java对象 addFunctionOfClassMethod*/
@Test
public void obj_method_addFunctionOfClassMethod() throws Exception{ExpressRunner runner = new ExpressRunner(false, false);String expressStr = "打印('jim')";// 使用QLExpress用于将一个用户自己定义的对象(例如Spring对象)方法转换为一个表达式计算的函数runner.addFunctionOfClassMethod("打印",Student.class.getName(),"print", new String[]{"String"},null);Object rst = runner.execute(expressStr, null, null, true, false);System.out.println(rst);
}

说明:addFunctionOfClassMethod方法含义为

用于将一个用户自己定义的对象(例如Spring对象)方法转换为一个表达式计算的函数。

该方法的源码为:

/*** 添加一个类的函数定义,例如:Math.abs(double) 映射为表达式中的 "取绝对值(-5.0)"** @param name           函数名称* @param className      类名称* @param functionName   类中的方法名称* @param parameterTypes 方法的参数类型名称* @param errorInfo      如果函数执行的结果是false,需要输出的错误信息* @throws Exception*/
public void addFunctionOfClassMethod(String name, String className, String functionName, String[] parameterTypes,String errorInfo) throws Exception {OperatorSelfDefineClassFunction operatorSelfDefineClassFunction = new OperatorSelfDefineClassFunction(name,className, functionName, parameterTypes, null, null, errorInfo);this.addFunction(name, operatorSelfDefineClassFunction);
}

4.测试调用java对象的方法2

/**** 测试调用java对象 addFunctionOfClassMethod*/
@Test
public void obj_method_addFunctionOfServiceMethod() throws Exception{ExpressRunner runner = new ExpressRunner(false, false);String expressStr = "打印('jim')";// 使用QLExpressrunner.addFunctionOfServiceMethod("打印",new Student(),"print", new String[]{"String"},null);Object rst = runner.execute(expressStr, null, null, true, false);System.out.println(rst);
}

addFunctionOfClassMethod 方法用于将用户定义的对象的方法转换为表达式计算的函数

/*** 用于将一个用户自己定义的对象(例如Spring对象)方法转换为一个表达式计算的函数** @param name* @param serviceObject* @param functionName* @param parameterTypes* @param errorInfo* @throws Exception*/
public void addFunctionOfServiceMethod(String name, Object serviceObject, String functionName,String[] parameterTypes, String errorInfo) throws Exception {OperatorSelfDefineServiceFunction operatorSelfDefineServiceFunction = new OperatorSelfDefineServiceFunction(name, serviceObject, functionName, parameterTypes, null, null, errorInfo);this.addFunction(name, operatorSelfDefineServiceFunction);
}

总结:

通过测试QLExpress操作java对象,我们学习了addFunctionOfClassMethod 方法,我们可以把一个java类中的方法,转化为QLExpress表达式函数。

最近笔者创建了一个圈子https://pc.fenchuan8.com/#/index?forum=58055&yqm=9HKS

欢迎大家加入一起交流学习。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

发布 Whatsonchain 上的 BSV20 插件

我们发布了 whatsonchain 上的 BSV20 插件来验证 BSV20 代币。 对于任何交易&#xff0c;whatsonchain 都可以通过以下网址打开&#xff1a; https://whatsonchain.com/tx/{hash}我们使用此 bsv20 v21 交易 打开 Whatsonchain 。 打开whatsonchain后你会看到BSV20插件&#x…

Linux系统安装MySQL8.0版本详细教程【亲测有效】

首先官网下载安装包&#xff1a;https://downloads.mysql.com/archives/community/ 一、上传到安装服务器 二、解压 tar -xvf mysql-8.0.31-linux-glibc2.12-x86_64.tar.xz三、移动位置并重新命名 mv mysql-8.0.31-linux-glibc2.12-x86_64 /usr/local/mysql四、创建mysql用户…

官宣 | HelpLook已入驻企业微信应用市场

HelpLook正式入驻企业微信第三方应用市场。 HelpLook支持自定义域名与AI站内搜索&#xff0c;能够帮助企业微信用户搭建所见即所得的企业知识库、产品帮助中心、用户手册、企业博客。 | 怎么找到HelpLook并开始使用 在企业微信的第三方应用就可直接搜索HelpLook&#xff0c;添…

虚幻学习笔记14—重叠和碰撞事件

一、前言 在开发应用当中两个物体的重叠和碰撞事件会经常用到&#xff0c;在虚幻中哲两个有很大的区别&#xff0c;在官方文档碰撞概述其实已经讲了怎样发生碰撞和重叠&#xff0c;但是还是遗漏不少注意事项合细节&#xff0c;主要文档写的太粗糙了&#xff0c;这也让我在使用的…

Docker Compose入门:打造多容器应用的完美舞台

Docker Compose 是一个强大的工具&#xff0c;它允许开发者通过简单的 YAML 文件定义和管理多容器的应用。本文将深入讨论 Docker Compose 的基本概念、常用命令以及高级应用场景&#xff0c;并通过更为丰富和实际的示例代码&#xff0c;助您轻松掌握如何通过 Docker Compose 打…

数据结构和算法 - 前置扫盲

数据结构和算法 一、前置扫盲 1、数据结构分类 1.1 逻辑结构&#xff1a;线性与非线性 tip&#xff1a;逻辑结构揭示了数据元素之间的逻辑关系。 线性数据结构&#xff1a;元素间存在明确的顺序关系。 数据按照一定顺序排列&#xff0c;其中元素之间存在一个对应关系&#x…

Liunx系统挂载磁盘

1.具体步骤 大概五个步骤 添加磁盘磁盘分区格式化分区挂载分区到指定目录设置开机自动挂载 目标将sdb1分区挂载到/data目录 2.添加磁盘 使用lsblk -f命令可以查看当前系统磁盘情况 lsblk -f 可以看到已经有一个磁盘sda&#xff0c;现在我们给虚拟机增加一个磁盘 添加完成后…

数据结构与算法:插入排序

原理 保证区间内排好顺序&#xff0c;逐渐将区间外数据插入到该区间中。 从局部扩散到整体。 第一次&#xff1a;保证0-1范围内有序 arr[0]和arr[1]对比&#xff0c;若arr[0] 大于 arr[1] &#xff0c;交换两个值&#xff0c; 0-1范围内有序。 第二次&#xff1a;保证 0-2 …

力扣题:数字与字符串间转换-12.14

力扣题-12.14 [力扣刷题攻略] Re&#xff1a;从零开始的力扣刷题生活 力扣题1&#xff1a;442. 数组中重复的数据 解题思想&#xff1a;从字符串中能够正确提取数字即可 class Solution(object):def complexNumberMultiply(self, num1, num2):""":type num1:…

2.5 常规游戏中模型通用要求介绍

一、布线和理性 多星点&#xff08;4个及4个以上边的交点&#xff09; 如果是在中模阶段&#xff0c;减少使用多星点&#xff0c;因为会在细分是时出现凸点问题&#xff0c;如果要使用多星点&#xff0c;需要通过布线技巧把它移动至平面处&#xff0c;不要让他出现在倒角边缘。…

科技提升安全,基于DETR【DEtection TRansformer】模型开发构建商超扶梯场景下行人安全行为姿态检测识别系统

在商超等人流量较为密集的场景下经常会报道出现一些行人在扶梯上摔倒、受伤等问题&#xff0c;随着AI技术的快速发展与不断普及&#xff0c;越来越多的商超、地铁等场景开始加装专用的安全检测预警系统&#xff0c;核心工作原理即使AI模型与摄像头图像视频流的实时计算&#xf…

深入理解Java虚拟机---Java内存模型

JMM Java内存模型主内存和工作内存volatile Java内存模型 Java内存模型是Java虚拟机规范中试图定义一种Java内存模型(JMM)来屏蔽掉各种硬件和操作系统的内存访问差异&#xff0c;以实现让Java程序在各种平台上都能达到一致的内存访问效果。可以理解为JMM定义一套在多线程读写共…

计算机网络简答题

面向连接和非连接的服务特点 面向连接的服务&#xff1a;通信双方在进行通信之前&#xff0c;要事先建立一个完整的可以彼此沟通的通道&#xff0c;在通信过程中整个连接的情况可以被实时的监控和管理 面向非链接的服务&#xff1a;不需要预先建立一个联络两个通信节点的连接&a…

智能优化算法应用:基于平衡优化器算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于平衡优化器算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于平衡优化器算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.平衡优化器算法4.实验参数设定5.算法…

每日一题:Leetcode1926.迷宫中离入口最近的出口

给你一个 m x n 的迷宫矩阵 maze &#xff08;下标从 0 开始&#xff09;&#xff0c;矩阵中有空格子&#xff08;用 . 表示&#xff09;和墙&#xff08;用 表示&#xff09;。同时给你迷宫的入口 entrance &#xff0c;用 entrance [entrancerow, entrancecol] 表示你一开始…

HBase 高可用集群详细图文安装部署

目录 一、HBase 安装部署 1.1 Zookeeper 正常部署 1.2 Hadoop 正常部署 1.3 HBase 安装 1.4 HBase 的配置文件 1.4.1 hbase-env.sh 1.4.2 hbase-site.xml 1.4.3 regionservers 1.4.4 创建目录 1.5 HBase 远程发送到其他节点 1.6 HBase 服务的启动 1.6.1 单点…

分类预测 | Matlab实现HPO-GRU【23年新算法】基于猎食者优化算法优化门控循环单元的数据分类预测

分类预测 | Matlab实现DBO-SVM蜣螂算法优化支持向量机的数据分类预测【23年新算法】 目录 分类预测 | Matlab实现DBO-SVM蜣螂算法优化支持向量机的数据分类预测【23年新算法】分类效果基本描述程序设计参考资料 分类效果 基本描述 1.HPO-GRU【23年新算法】基于猎食者优化算法优…

【电子取证:FTK IMAGER 篇】DD、E01系统镜像动态仿真

​ 文章目录 【电子取证&#xff1a;FTK Imager 篇】DD、E01系统镜像动态仿真一、DD、E01系统镜像动态仿真 &#xff08;一&#xff09;使用到的软件 1、FTK Imager (v4.5.0.3)2、VMware Workstation 15 Pro (v15.5.2)&#xff08;二&#xff09;FTK Imager 挂载镜像 1、选择 …

学习深度强化学习---第3部分----RL蒙特卡罗相关算法

文章目录 3.1节 蒙特卡罗法简介3.2节 蒙特卡罗策略评估3.3节 蒙特卡罗强化学习3.4节 异策略蒙特卡罗法 本部分视频所在地址&#xff1a;深度强化学习的理论与实践 3.1节 蒙特卡罗法简介 在其他学科中的蒙特卡罗法是一种抽样的方法。 如果状态转移概率是已知的&#xff0c;则是…

vue的computed中的getter和setter

vue的computed中的getter和setter 定义getter写法setter写法 定义 computed 中可以分成 getter&#xff08;读取&#xff09; 和 setter&#xff08;设值&#xff09;&#xff0c;一般情况下是没有 setter 的&#xff0c;computed 预设只有 getter&#xff0c;也就是只能读取&a…