JAVA计算字符串数学表达式
作用:
给定一个字符串描述的算术表达式,计算出结果值。
输入字符串长度不超过 100 ,合法的字符包括 ”+, -, *, /, (, )” , ”0-9” 。
例如:
入参:"(5-1)*3" :输出:12
入参:"16/2" :输出:8
/**
** 计算数学表达式
* @param expressions 表达式
* @return int 计算结果
* @author yinqi
* @create 2024/3/21 18:27
**/
public static int calculateMathExpressions(String expressions) {
Stack<Integer> stack_nums = new Stack<>();
Stack<Character> stack_symbol = new Stack<>();
Map<Character, Integer> map = new HashMap<>();
map.put('+', 1);
map.put('-', 1);
map.put('*', 2);
map.put('/', 2);
if (expressions.charAt(0) == '-') {//第一个数为负数
expressions = "0" + expressions;
}
expressions = expressions.replace("(-", "(0-");//其他位置负数处理
for (int i = 0; i < expressions.length(); i++) {
char ch = expressions.charAt(i);
if (ch == ' ') continue;
if (ch == '(') {
stack_symbol.push(ch);
continue;
}
if (ch == ')') {
//括号结束计算一次
stack_nums.push(calculate(stack_nums, stack_symbol));
if (!stack_symbol.isEmpty() && stack_symbol.peek() == '(') {
//当前计算是括号内最后一次运算,弹出左括号
stack_symbol.pop();
}
continue;
}
if (map.containsKey(ch)) {
// 栈内至少有1个运算符且栈顶不是左括号,并且栈内运算符优先级大于等于当前运算符号优先级,执行一次计算,
// 即先消费已入栈的高优先级运算符
while (!stack_symbol.isEmpty() && stack_symbol.peek() != '(' && map.get(stack_symbol.peek()) >= map.get(ch)) {
stack_nums.push(calculate(stack_nums, stack_symbol));
}
stack_symbol.push(ch);
} else {
int num = 0;
int j = i;//循环读取十进制整数
while (j < expressions.length() && Character.isDigit(expressions.charAt(j))) {
num = num * 10 + expressions.charAt(j) - '0';
j++;
}
stack_nums.push(num);
i = j - 1;
}
}
// 循环结束还有未算尽的式子,优先级低
while (!stack_symbol.isEmpty()) {
stack_nums.push(calculate(stack_nums, stack_symbol));
if (!stack_symbol.isEmpty() && stack_symbol.peek() == '(') {
stack_symbol.pop();
}
}
return stack_nums.pop();
}
/**
* 执行运算
* @param stack_nums 操作数栈
* @param stack_symbol 运算符栈
* @return
*/
public static int calculate(Stack<Integer> stack_nums, Stack<Character> stack_symbol) {
int res = 0;
int opt_nums2 = stack_nums.pop();
int opt_nums1 = stack_nums.pop();
char symbol = stack_symbol.pop();
switch (symbol) {
case '+': {
res = opt_nums1 + opt_nums2;
break;
}
case '-': {
res = opt_nums1 - opt_nums2;
break;
}
case '*': {
res = opt_nums1 * opt_nums2;
break;
}
case '/': {
res = opt_nums1 / opt_nums2;
break;
}
}
return res;
}
java处理SQL中的占位符和表达式
作用:
传入初始的带占位符的sql语句和参数,替换占位符并计算sql中的表达式后返回最终可执行的sql。
表达式:#{}
字符串占位符:'${}'
整数占位符:${}
当前页:${currentPage}
每页显示记录数:${pageSize}
mySql分页:limit #{(${currentPage} - 1) * ${pageSize}}, ${pageSize}
例如:
输入:
String sql2 = " select * from sys_user where status = '${status}'
and sort < #{${currentPage}*${pageSize}}
and sort > #{ (${currentPage} - 1) * ${pageSize} } ";
Map<String, Object> params = new HashMap<>();
params.put("status", 0);
params.put("login_name", "%a%");
params.put("currentPage", 5);
params.put("pageSize", 10);
输出:
select * from sys_user where status = '0' and sort < 50 and sort > 40
代码:
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ScreenConfigUtil {
/**
** 替换占位符
* @param sql
* @param params
* @return java.lang.String
* @author yinqi
* @create 2024/3/21 18:42
**/
public static String replaceSqlPlaceholders(String sql, Map<String, Object> params) {
Pattern pattern = Pattern.compile("\\$\\{(.+?)\\}");
Matcher matcher = pattern.matcher(sql);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
String placeholder = matcher.group(1);
Object value = params.get(placeholder);
String replacement = value != null ? value.toString() : "";
matcher.appendReplacement(sb, replacement);
}
matcher.appendTail(sb);
return sb.toString();
}
/**
** 提取#{}里面的内容
* @param input
* @return java.lang.String
* @author yinqi
* @create 2024/3/21 18:34
**/
public static List<String> extractValues(String input) {
List<String> values = new ArrayList<>();
Pattern pattern = Pattern.compile("#\\{(.*?)\\}");
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
values.add(matcher.group(1));
}
return values;
}
/**
** 使用map中的value替换str字符串中的key
* @param str
* @param expressValMap
* @return java.lang.String
* @author yinqi
* @create 2024/3/21 18:38
**/
public static String replaceValue(String str, HashMap<String, String> expressValMap) {
for (String key : expressValMap.keySet()){
String val = expressValMap.get(key);
str = str.replace(key, val);
}
return str;
}
/**
** 计算数学表达式
* @param expressions 表达式
* @return int 计算结果
* @author yinqi
* @create 2024/3/21 18:27
**/
public static int calculateMathExpressions(String expressions) {
Stack<Integer> stack_nums = new Stack<>();
Stack<Character> stack_symbol = new Stack<>();
Map<Character, Integer> map = new HashMap<>();
map.put('+', 1);
map.put('-', 1);
map.put('*', 2);
map.put('/', 2);
if (expressions.charAt(0) == '-') {//第一个数为负数
expressions = "0" + expressions;
}
expressions = expressions.replace("(-", "(0-");//其他位置负数处理
for (int i = 0; i < expressions.length(); i++) {
char ch = expressions.charAt(i);
if (ch == ' ') continue;
if (ch == '(') {
stack_symbol.push(ch);
continue;
}
if (ch == ')') {
//括号结束计算一次
stack_nums.push(calculate(stack_nums, stack_symbol));
if (!stack_symbol.isEmpty() && stack_symbol.peek() == '(') {
//当前计算是括号内最后一次运算,弹出左括号
stack_symbol.pop();
}
continue;
}
if (map.containsKey(ch)) {
// 栈内至少有1个运算符且栈顶不是左括号,并且栈内运算符优先级大于等于当前运算符号优先级,执行一次计算,
// 即先消费已入栈的高优先级运算符
while (!stack_symbol.isEmpty() && stack_symbol.peek() != '(' && map.get(stack_symbol.peek()) >= map.get(ch)) {
stack_nums.push(calculate(stack_nums, stack_symbol));
}
stack_symbol.push(ch);
} else {
int num = 0;
int j = i;//循环读取十进制整数
while (j < expressions.length() && Character.isDigit(expressions.charAt(j))) {
num = num * 10 + expressions.charAt(j) - '0';
j++;
}
stack_nums.push(num);
i = j - 1;
}
}
// 循环结束还有未算尽的式子,优先级低
while (!stack_symbol.isEmpty()) {
stack_nums.push(calculate(stack_nums, stack_symbol));
if (!stack_symbol.isEmpty() && stack_symbol.peek() == '(') {
stack_symbol.pop();
}
}
return stack_nums.pop();
}
/**
* 执行运算
* @param stack_nums 操作数栈
* @param stack_symbol 运算符栈
* @return
*/
public static int calculate(Stack<Integer> stack_nums, Stack<Character> stack_symbol) {
int res = 0;
int opt_nums2 = stack_nums.pop();
int opt_nums1 = stack_nums.pop();
char symbol = stack_symbol.pop();
switch (symbol) {
case '+': {
res = opt_nums1 + opt_nums2;
break;
}
case '-': {
res = opt_nums1 - opt_nums2;
break;
}
case '*': {
res = opt_nums1 * opt_nums2;
break;
}
case '/': {
res = opt_nums1 / opt_nums2;
break;
}
}
return res;
}
/**
** 传入初始的sql,处理后返回最终可执行的sql
* @param sql
* @param params
* @return java.lang.String
* @author yinqi
* @create 2024/3/21 18:48
**/
public static String getSql(String sql, Map<String, Object> params) {
// 替换占位符
String result = replaceSqlPlaceholders(sql, params);
// 提取#{}里面的内容
List<String> expressList = extractValues(result);
if (CollectionUtil.isNotEmpty(expressList)){
// 存放键值对 --> 表达式:表达式计算结果
HashMap<String, String> expressValMap = new HashMap<>();
// 计算表达式的值
for(String express : expressList){
int expressResult = calculateMathExpressions(express);
expressValMap.put("#{" + express + "}", String.valueOf(expressResult));
}
// 使用新值替换#{}
result = replaceValue(result, expressValMap);
}
return result;
}
public static void main(String[] args) {
String sql1 = "select * from sdp_sys_user where status = '${status}' and login_name like '${login_name}' limit #{ (${currentPage} - 1) * ${pageSize} }, ${pageSize}";
String sql2 = " select * from sdp_sys_user where status = '${status}' and sort < #{${currentPage}*${pageSize}} and sort > #{ (${currentPage} - 1) * ${pageSize} } ";
Map<String, Object> params = new HashMap<>();
params.put("status", 0);
params.put("login_name", "%a%");
params.put("currentPage", 5);
params.put("pageSize", 10);
String resultSql1 = getSql(sql1, params);
String resultSql2 = getSql(sql2, params);
System.out.println("原来的sql1:"+sql1);
System.out.println("最终的sql1:"+resultSql1);
System.out.println("------------------------------------------------------------------------------------------");
System.out.println("原来的sql2:"+sql2);
System.out.println("最终的sql2:"+resultSql2);
}
}
VUE中实现codemirror组件中失去焦点时,向codemirror中鼠标所在位置插入指定字符串
在data
中定义一个变量来保存鼠标焦点所在的位置。然后,在失去焦点时,调用Codemirror实例的getCursor()
方法获取鼠标焦点的位置。最后,调用replaceRange()
方法插入指定的字符串到鼠标焦点位置。
cmOptions
需要根据实际需求进行配置。
<template>
<codemirror
ref="mycode"
:value="newFormData.sql"
:options="cmOptions"
@blur="codemirrorBlur()"
/>
</template>
<script>
import 'codemirror/addon/display/autoRefresh.js';
export default {
data() {
return {
cursor: null, // 保存鼠标焦点位置
newFormData: {
sql: ''
},
cmOptions: {
// codemirror的配置选项
tabSize: 4,
mode: "text/x-mariadb", //选择对应代码编辑器的语言
theme: "midnight", //主题
lineNumbers: true,
line: true,
autoRefresh: true
}
};
},
methods: {
codemirrorBlur() {
// 失去焦点时的处理逻辑
this.cursor = this.$refs.mycode.codemirror.getCursor(); // 获取鼠标焦点位置
this.$refs.mycode.codemirror.replaceRange('自动插入的字符串', this.cursor); // 插入指定字符串到鼠标焦点位置
}
}
};
</script>