Java对字符串形式的公式进行计算

使用场景: 需要执行一些可配置的公式来计算结果
例如:某些公司工资的计算,分各种计算方案,拿到对应字段替换到公式中进行结果计算

依赖

    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-jexl3</artifactId>
      <version>3.1</version>
    </dependency>

    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-text</artifactId>
      <version>1.3</version>
    </dependency>

代码

package com.hzr;

import org.apache.commons.jexl3.*;
import org.apache.commons.text.StringSubstitutor;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import java.math.BigDecimal;
import java.util.*;

public class MyTest {

	public static void main(String[] args) {


		Map<String,Object> varMap = new HashMap<>();
		varMap.put("绩效工资",1000);
		varMap.put("年平均月工作日",21.75);
		varMap.put("请假天数",20);

		/**
		 * 方法一
		 */
		String ex = "${绩效工资}/${年平均月工作日}*${请假天数}";
		System.out.println(jexlEval(ex,varMap));

		/**
		 * 方法二
		 */
		try {
			System.out.println(jsEval(ex,varMap));
		} catch (ScriptException e) {
			e.printStackTrace();
		}


		/**
		 * 方法三
		 */
		Map<String,Object> varMap2 = new HashMap<>();
		varMap2.put("a",1000);
		varMap2.put("b",21.75);
		varMap2.put("c",20);
		String ex2 = "a/b*c";
		System.out.println(jexlEval2(ex2,varMap2));

	}

	/**
	 * 占位符 + ScriptEngine 方式
	 * @param formula
	 * @return
	 * @throws ScriptException
	 */
	public static Object jsEval(String formula,Map<String,Object> varMap) throws ScriptException {
		formula = new StringSubstitutor(varMap).replace(formula);
		ScriptEngine jse = new ScriptEngineManager().getEngineByName("JavaScript");
		Object evaluate = jse.eval(formula);
		return new BigDecimal(evaluate.toString()).setScale(2,BigDecimal.ROUND_HALF_UP).toString();
	}

	/**
	 * 占位符公式 + Jexl  支持中文占位符
	 * @param formula
	 * @param varMap
	 * @return
	 */
	public static Object jexlEval(String formula, Map<String,Object> varMap){
		formula = new StringSubstitutor(varMap).replace(formula);

		JexlEngine jexlEngine = new JexlBuilder().create();
		JexlExpression jexlExpression = jexlEngine.createExpression(formula);
		Object evaluate = jexlExpression.evaluate(null);
		return new BigDecimal(evaluate.toString()).setScale(2,BigDecimal.ROUND_HALF_UP).toString();
	}

	/**
	 * 变量公式 + JexlContext  不支持中文公式
	 * @param formula
	 * @param varMap
	 * @return
	 */
	public static Object jexlEval2(String formula, Map<String,Object> varMap){
		JexlContext jc = new MapContext();
		varMap.forEach((key,value) ->{
			jc.set(key,value);
		});

		JexlEngine jexlEngine = new JexlBuilder().create();
		JexlExpression jexlExpression = jexlEngine.createExpression(formula);
		Object evaluate = jexlExpression.evaluate(jc);
		return new BigDecimal(evaluate.toString()).setScale(2,BigDecimal.ROUND_HALF_UP).toString();
	}
}



输出结果

919.54
919.54
919.54
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值