## MVEL实现java直接根据公式计算结果 原

V
ValSong

``````import java.math.BigDecimal;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;

import org.mvel2.CompileException;
import org.mvel2.MVEL;
import org.mvel2.PropertyAccessException;

/**
* 计算工具
*
* @author valsong
* @date Jul 24, 2017
*
*/
public class CalculateUtils {

/**
* 根据传入的公式和参数进行计算
*
* @param formula
* @param variables
* @return
*/
public static <T> BigDecimal calculate(String formula, Map<String, T> variables) {
if (SimpleStringUtils.isBlank(formula)) {
throw new CalculateException("MVEL formula can't be null! formula : " + formula); // 公式不能为空
}
if (variables == null || variables.size() == 0) {
throw new CalculateException("MVEL variables can't be null! variables : " + String.valueOf(variables)); // 参数不能为空
}

try {
// 将公式中的变量全部转化为BigDecimal类型
variables.entrySet().stream().filter(e -> e != null && e.getKey() != null && e.getValue() != null)
.map(CalculateUtils::convert).collect(Collectors.toMap(Entry::getKey, Entry::getValue));

} catch (NumberFormatException e) {
throw new CalculateException(
"MVEL can't convert to BigDecimal, please check the variables : " + String.valueOf(variables) + "!",
e);
} catch (Exception e) {
throw e;
}
BigDecimal result = null;
try {
result = (BigDecimal) MVEL.eval(formula, variables);
} catch (PropertyAccessException pae) {
throw new CalculateException(
"MVEL please check the formula :" + formula + " & variables : " + String.valueOf(variables) + "!",
pae);
} catch (CompileException ce) {
throw new CalculateException("MVEL calculate error! ", ce);
} catch (Exception e) {
throw e;
}
return result;
}

/**
* 将参数转化为Bigdecimal类型
*
* @param entry
* @return
*/
@SuppressWarnings("unchecked")
public static <T> Entry<String, T> convert(Entry<String, T> entry) {
if (entry != null) {
BigDecimal value = null;
if (entry.getValue() instanceof BigDecimal) {
value = (BigDecimal) entry.getValue();
} else {
value = NumberUtils.getNum(NumberUtils.getNum(entry.getValue()));
}
entry.setValue((T) value);
}
return entry;
}

}
``````

``````
/**
* 计算异常
*
* @author Val Song
* @date   Jul 28, 2017
*
*/
public class CalculateException extends RuntimeException {
private static final long serialVersionUID = 5162710183389028792L;

/**
* Constructs a {@code CalculateException} with no detail message.
*/
public CalculateException() {
super();
}

/**
* Constructs a {@code CalculateException} with the specified detail
* message.
*
* @param message
*            the detail message.
*/
public CalculateException(String message) {
super(message);
}

/**
* Constructs a {@code CalculateException} with the specified detail
* message & cause
*
* @param message
* @param cause
*/
public CalculateException(String message, Throwable cause) {
super(message, cause);
}

}

``````

``````
/**
* 字符串工具
*
* @author valsong
*
*/
public class SimpleStringUtils {

/**
* 判断字符串不为空
*
* @param str
* @return
*/
public static boolean isNotBlank(String str) {
return !isBlank(str);
}

/**
* 判断字符串为空
*
* @param str
* @return
*/
public static boolean isBlank(String str) {
if (str == null || "".equals(str.trim())) {
return true;
}
return false;
}

/**
*  去首尾空格
*
* @param s
* @return
*/
public static <T> String trim(T s) {
if (s instanceof String) {
return s == null ? null : ((String) s).trim();
} else {
return s == null ? null : String.valueOf(s).trim();
}
}

/**
* 下划线命名转驼峰式
*
* @param str
* @return
*/
public static String toCamel(String str) {
if (SimpleStringUtils.isBlank(str)) {
return str;
}
StringBuffer buffer = new StringBuffer();
str = str.toLowerCase().trim();
char[] charArray = str.toCharArray();
if (charArray != null) {
for (int i = 0; i < charArray.length; i++) {
if ('_' == charArray[i]) {
i = i + 1;
buffer.append(Character.toUpperCase(charArray[i]));
} else {
buffer.append(charArray[i]);
}
}
}
return buffer.toString();
}

/**
* 驼峰转下划线
*
* @param str
* @return
*/
public static String toUnderline(String str) {
if (SimpleStringUtils.isBlank(str)) {
return str;
}
StringBuffer buffer = new StringBuffer();
str = str.trim();
char[] charArray = str.toCharArray();
if (charArray != null) {
for (int i = 0; i < charArray.length; i++) {
if (Character.isUpperCase(charArray[i])) {
buffer.append("_");
buffer.append(Character.toLowerCase(charArray[i]));
} else {
buffer.append(charArray[i]);
}
}
}
return buffer.toString();
}

}

``````

``````
public class CalculateUtilsTest {

/**
* 20 * 100 - ( 30 -20 ) + 20 ^ 3 + 20/2
*/
@Test
public void calculateTest4() {

String formula = "A * B - (C -D) + E.pow(F) + G / H";

Map<String, Object> variables = new HashMap<>();
variables.put("A", "20");
variables.put("B", 100L);
variables.put("C", 30.0D);
variables.put("D", 20);
variables.put("E", new BigDecimal("20"));
variables.put("F", "3");
variables.put("G", "20");
variables.put("H", "2");

BigDecimal result = CalculateUtils.calculate(formula, variables);
Assert.assertTrue(new BigDecimal("10000.0").compareTo(result) == 0);
}

}

``````

V

### ValSong

【Java】Fel计算引擎学习

kisscatforever
2018/05/23
0
0
Binomial Coefficient（二项式系数）

In mathematics, any of the positive integers that occurs as a coefficient in the binomial theorem is a binomial coefficient. Commonly, a binomial coefficient is indexed by a pai......

honeymose
2018/12/30
0
0

Java 的 SoftReference 有很多年都没有被人惦记了。在 Javadoc 里, 它的描述是这样： ”虚拟机在抛出 OutOfMemoryError 之前会保证所有的软引用对象已被清除。此外，没有任何约束保证软引用将...

2013/08/12
0
0
OutOfMemoryError: unable to create new native t...

Yohance
2013/06/07
0
1

Mr&Cheng
2013/02/28
0
0

linuxprobe16
16分钟前
0
0
MicroPython技术及应用前景

1 Micropython技术是什么？ MicroPython极精简高效的实现了Python3语言。它包含Python标准库的一小部分，能在单片机和受限环境中运行。 1.1 MicroPython发展 由剑桥大学的理论物理学家乔治....

bodasisiter
22分钟前
0
0

30分钟前
0
0
🛠️Hanjst/汉吉斯特更新加JavaScript运行时优化等

2
0
OSChina 周六乱弹 —— 舔狗是没有好下场的

Osc乱弹歌单（2019）请戳（这里） 【今日歌曲】 @我没有抓狂 ：#今天听什么# #今天听这个# 分享 Nirvana 的歌曲《Smells Like Teen Spi...》 《Smells Like Teen Spi...》- Nirvana 手机党少...

463
13