java算子介绍
包含
- 均值
- 最大值
- 最小值
- 最大最小值范围
- 周期计数器(计算最长子串出现次数)
- 值计数器(计算每个字符出现次数)
- 公式计算器(计算加减乘除、绝对值、总体标准差、总体方差)自动识别
- 逻辑表达式
- 变化速率(一段时间内变化速率)
源码
package com.iscas.biz.report.utils;
/**
* @author yichuan@iscas.ac.cn
* @version 1.0
* @date 2021/5/10 9:39
* @describe public 方法表示外部可调用方法,private作为内部算子调用
* get开头的方法可以传入list,非get开发方法只支持单数值传入
*/
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* 算子工具类
*/
public class OperatorUtils {
public static void main(String[] args) {
List<Double> list = Arrays.asList(0.00, 1.00, 1.24, 3.00);
Double average = getAverageValue(list);
Double max = getMaxValue(list);
Double min = getMinValue(list);
Map map = getRangeValue(list);
System.out.println("测试数据"+list);
System.out.println("0-均值测试"+average);
System.out.println("1-最大值测试"+max);
System.out.println("2-最小值测试"+min);
System.out.println("3-最大最小值范围测试"+map.toString());
List<String> list2 = Arrays.asList("abcabc","abababa");
System.out.println("测试数据"+list2);
List<Map<String,Integer>> cycleMapList = getCycleValue(list2);
List<Map<Character,Integer>> countMapList = getCountValue(list2);
System.out.println("4-周期计数器测试"+cycleMapList.toString());
System.out.println("5-值计数器测试"+countMapList.toString());
/** 变量和值的key-value **/
Map<String,Double> varValue = new HashMap(){
{
put("a","1");
put("b","2");
}
};
/**要计算的公式**/
String formula = "a+4*b+3*abs(-10)+var(13,23,12,44,55)-std(13,23,12,44,55)";
System.out.println("6-公式计算器 变量值"+varValue);
System.out.println("6-公式计算器 公式"+formula);
System.out.println("6 公式计算器最终结果"+getFormulaValue(formula,varValue));
List<Double> list3 = Arrays.asList(13.0,23.0,12.0,44.0,55.0);
System.out.println("6-1公式计算器之绝对值测试-输入-13.0 输出"+abs(-13.0));
OperatorUtils operatorUtils = new OperatorUtils();
System.out.println("6-2公式计算器之平方根测试-输入4.0 输出"+operatorUtils.mySqrt(4.0));
System.out.println("测试数据"+list3);
System.out.println("6-3公式计算器之总体标准偏差的方差"+getVarianceValue(list3));
System.out.println("6-4公式计算器之样本标准偏差的方差"+getSampleVarianceValue(list3));
System.out.println("6-5公式计算器之总体标准偏差"+getStandardDeviationValue(list3));
System.out.println("6-6公式计算器之样本标准偏差"+getSampleStandardDeviationValue(list3));
List<String> list4 = Arrays.asList("!(f)","|(f,t)","&(t,f)","|(&(t,f,t),!(t))");
System.out.println("测试数据"+list4);
List<Map<String, Boolean>> logicMapList = getLogicValue(list4);
System.out.println("7-逻辑表达式测试"+logicMapList.toString());
Map<String,String> rateMap1 = new HashMap<String,String>(){
{
put("start","2021-03-11 13:40:58");
put("end","2021-03-11 13:41:58");
put("value","133");
put("name","lisi");
}
};
Map<String,String> rateMap2 = new HashMap<String,String>(){
{
put("start","2021-03-11 13:30:58");
put("end","2021-03-11 13:52:58");
put("value","99999");
put("name","zhangsan");
}
};
List<Map<String,String>> rateMapList = new ArrayList<>();
rateMapList.add(rateMap1);
rateMapList.add(rateMap2);
Double rateResult= getRateValue(rateMapList);
System.out.println("测试数据"+rateMapList);
System.out.println("8-变化速率测试"+rateResult);
}
/**
* 0号算子:计算均值
*/
public static double getAverageValue(List<Double> list){
Double average = list.stream().mapToDouble(Double::doubleValue).average().orElse(0);
return average;
}
/**
* 1号算子:计算最大值
*/
public static double getMaxValue(List<Double> list){
Double max = list.stream().max(Double::compareTo).get();
return max;
}
/**
* 2号算子:计算最大值
*/
public static double getMinValue(List<Double> list){
Double min = list.stream().min(Double::compareTo).get();
return min;
}
/**
* 3号算子:计算最大最小值范围
*/
public static Map<String,Double> getRangeValue(List<Double> list){
Double max = list.stream().max(Double::compareTo).get();
Double min = list.stream().min(Double::compareTo).get();
Map map = new HashMap();
map.put("max",max);
map.put("min",min);
return map;
}
/**
* 4号算子:周期计数器:计算多少个字符算一个周期
*/
public static List<Map<String,Integer>> getCycleValue(List<String> list){
List<Map<String,Integer>> resultList = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
HashMap<String,Integer> hashMap = new HashMap<>();
String s = list.get(i);
int cycleNumber = s.length()/lengthOfLongestSubstring(s);
hashMap.put(s,cycleNumber);
resultList.add(hashMap);
}
return resultList;
}
/**
* 4号算子所用方法,用于找出无重复字符的最长子串
* @param s
* @return
*/
private static int lengthOfLongestSubstring(String s) {
// 记录字符上一次出现的位置
int[] last = new int[128];
for(int i = 0; i < 128; i++) {
last[i] = -1;
}
int n = s.length();
int res = 0;
int start = 0; // 窗口开始位置
for(int i = 0; i < n; i++) {
int index = s.charAt(i);
start = Math.max(start, last[index] + 1);
res = Math.max(res, i - start + 1);
last[index] = i;
}
return res;
}
/**
* 5号算子:值计数器
*/
public static List<Map<Character,Integer>> getCountValue(List<String> list){
List<Map<Character,Integer>> resultList = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
HashMap<Character,Integer> hashMap = new HashMap<>();
String charArray = list.get(i);
char[] arr = charArray.toCharArray();
for (char c : arr){
if (!hashMap.containsKey(c))
hashMap.put(c,1);
else
hashMap.put(c,hashMap.get(c)+1);
}
resultList.add(hashMap);
}
return resultList;
}
/***
*6号算子入口 :公式计算器
*/
private static Float getFormulaValue(String formula,Map<String,Double> varValue){
/**先计算绝对值,标准差,方差*/
String newFormula = calcPlus(formula);
/** 变量值代回公式进行替换 **/
String finallyFormula = replaceEquation(newFormula,varValue);
/** 进行计算 **/
float result = calc(finallyFormula);
return result;
}
/**
* 6号算子 转换List<String>为List<Double>
*/
public static <T, U> List<U> convertStringListTodoubleList(List<T> listOfString, Function<T, U> function){
return listOfString.stream()
.map(function)
.collect(Collectors.toList());
}
/**6号算子 高级运算 包括绝对值、方差、标准差
*/
private static String calcPlus(String formula){
//todo 目前一个公式中同一个高级运算符只能出现一次abs,var,std
/**公式计算器-提取abs绝对值输入值*/
String absFormula = getMatcher("abs\\((.+?)\\)", formula);
String absFormulaNumberBefore = getMatcher("\\((.+?)\\)",absFormula);
String absFormulaNumberAfter = absFormulaNumberBefore.replace("(","").replace(")","");
Double absValue = Double.parseDouble(absFormulaNumberAfter);
Double absResult = abs(absValue);
//计算结果替换回原来的公式
formula = formula.replace(absFormula,absResult.toString());
/**公式计算器-提取var方差输入值*/
String varFormula = getMatcher("var\\((\\d+,)*\\d+\\)", formula);
String varFormulaNumberBefore = getMatcher("\\((.+?)\\)",varFormula);
String varFormulaNumberAfter = varFormulaNumberBefore.replace("(","").replace(")","");
String [] varFormulaNumberArray = varFormulaNumberAfter.split(",");
List<String> varFormulaNumberList = Arrays.asList(varFormulaNumberArray);
List<Double> varListOfDouble = convertStringListTodoubleList(varFormulaNumberList,Double::parseDouble);
Double varResult = getVarianceValue(varListOfDouble);
//计算结果替换回原来的公式
formula = formula.replace(varFormula,varResult.toString());
/**公式计算器-提取std标准差输入值*/
String stdFormula = getMatcher("std\\((\\d+,)*\\d+\\)", formula);
String stdFormulaNumberBefore = getMatcher("\\((.+?)\\)",stdFormula);
String stdFormulaNumberAfter = stdFormulaNumberBefore.replace("(","").replace(")","");
String [] stdFormulaNumberArray = stdFormulaNumberAfter.split(",");
List<String> stdFormulaNumberList = Arrays.asList(stdFormulaNumberArray);
List<Double> stdListOfDouble = convertStringListTodoubleList(stdFormulaNumberList,Double::parseDouble);
Double stdResult = getStandardDeviationValue(stdListOfDouble);
//计算结果替换回原来的公式
formula = formula.replace(stdFormula,stdResult.toString());
return formula;
}
/**
*6号算子 用于匹配正则
* @param regex
* @param source
* @return
*/
private static String getMatcher(String regex, String source) {
String result = "";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(source);
while (matcher.find()) {
result = matcher.group();
}
return result;
}
/**6号算子 进行计算 **/
private static float calc(String newFormula) {
boolean stillHaveCalcSymbol = false;
do{
//System.out.println("before:" + newFormula);
/** 寻找最后一个左括号里面到第一个右括号里面1的内容 **/
char formulaArray[] = newFormula.toCharArray();
for (int i = 0; i < formulaArray.length; i++) {
if (formulaArray[i] == '+' || formulaArray[i] == '-'
|| formulaArray[i] == '*' || formulaArray[i] == '/'
|| formulaArray[i] == '(' || formulaArray[i] == ')') {
stillHaveCalcSymbol = true;
} else {
stillHaveCalcSymbol = false;
}
}
if (stillHaveCalcSymbol) {
String resultFormula = "";
//找最内层的括号里面的内容出来(含括号)
for (int i = 0; i < formulaArray.length; i++) {
if (formulaArray[i] == ')') {
int begin = 0;
for (int j = i; j >= 0; j--) {
if (formulaArray[j] == '(') {
begin = j;
break;
}
}
String calcString = newFormula.substring(begin, i + 1);
resultFormula = newFormula.replace(calcString, calcProc(calcString) + "");
break;
}
}
newFormula = resultFormula;
}
} while(stillHaveCalcSymbol);
//最后得到普通的顺序无括号公式:
//System.out.println(newFormula);
//最后一次计算:
float result = calcProc("(" + newFormula + ")");
return result;
}
/**6号算子 详细计算过程**/
private static float calcProc(String calcString) {
String calcSymbol[] = {"\\*", "\\/", "\\+", "\\-"};
char calcSymbolChar[] = {'*', '/', '+', '-'};
boolean haveSymbol = true;
float result = 0f;
while(haveSymbol){
//System.out.println("calcStr:" + calcString);
char calcCharArr[] = calcString.toCharArray();
result = 0f;
for (int i = 0; i < calcSymbol.length; i++) {
boolean alreadyFind = false;
for(int j = 0; j < calcCharArr.length; j++){
if(calcCharArr[j] == calcSymbolChar[i]){
//System.out.println("找到了" + calcSymbolChar[i]);
//以符号为中心,以左右两边的其他符号为边界找到两边的数
float num1 = 0f;
float num2 = 0f;
int bottom = 0;
for(int k = j - 1; k >= 0 && (calcCharArr[k] >= '0' && calcCharArr[k] <= '9' || calcCharArr[k] == '.') ; k--){
bottom = k;
}
num1 = Float.valueOf(calcString.substring(bottom, j));
//System.out.println("num1:" + num1);
int top = 0;
for(int k = j + 1; k < calcString.length() && (calcCharArr[k] >= '0' && calcCharArr[k] <= '9' || calcCharArr[k] == '.'); k++){
top = k;
}
num2 = Float.valueOf(calcString.substring(j + 1, top + 1));
//System.out.println("num2:" + num2);
switch(calcSymbolChar[i]){
case '*':
result = num1 * num2;
break;
case '/':
result = num1 / num2;
break;
case '+':
result = num1 + num2;
break;
case '-':
result = num1 - num2;
break;
}
calcString = calcString.replace(calcString.substring(bottom, top + 1), String.format("%.5f", result));
alreadyFind = true;
break;
}
}
if(alreadyFind) break;
}
haveSymbol = false;
if(calcString.contains("*") || calcString.contains("/") || calcString.contains("+") || calcString.contains("-")){
haveSymbol = true;
} else {
}
}
return result;
}
/**6号算子 变量代回公式进行替换 **/
private static String replaceEquation(String formula,Map<String,Double> varValue) {
String newFormula = new String(formula);
for (String key : varValue.keySet()){
newFormula = newFormula.replaceAll(key,varValue.get(key)+ "");
}
//System.out.println(newFormula);
return newFormula;
}
/**
* 6-1号算子:公式计算器之计算绝对值
*/
public static Double abs(Double a) {
return (a <= 0.0D) ? 0.0D - a : a;
}
/**
* 6-2号算子:公式计算器之计算平方根
*/
private Double s;
public Double mySqrt(Double x) {
s=x;
if(x==0D) return 0D;
return (sqrts(x));
}
public Double sqrts(Double x){
double res = (x + s / x) / 2;
if (res == x) {
return x;
} else {
return sqrts(res);
}
}
/**
* 6-3号算子:公式计算器之总体标准偏差的方差
*方差s^2=[(x1-x)^2+(x2-x)^2+......(xn-x)^2]/n(x为平均数)
* @return 总体标准偏差的方差 方差 常用
*/
public static Double getVarianceValue(List<Double> list) {
int n = list.size(); //数列元素个数
double avg = OperatorUtils.getAverageValue(list); //求平均值
double var = 0;
for (double i : list) {
var += (i-avg)*(i-avg); //(x1-x)^2+(x2-x)^2+......(xn-x)^2
}
return var/n;
}
/**
* 6-4号算子:公式计算器之样本标准偏差的方差
* 方差s^2=[(x1-x)^2+(x2-x)^2+......(xn-x)^2]/(n-1)(x为平均数)
* @return 样本标准偏差的方差 方差
*/
public static Double getSampleVarianceValue(List<Double> list) {
int n = list.size(); //数列元素个数
double avg = OperatorUtils.getAverageValue(list); //求平均值
double var = 0;
for (double i : list) {
var += (i-avg)*(i-avg); //(x1-x)^2+(x2-x)^2+......(xn-x)^2
}
return var/(n-1);
}
/**
* 6-5号算子:公式计算器之总体标准偏差
* 标准差σ=sqrt(s^2),即标准差=方差的平方根
* @return 总体标准偏差 标准差
*/
public static Double getStandardDeviationValue(List<Double> list){
OperatorUtils operatorUtils = new OperatorUtils();
DecimalFormat df = new DecimalFormat("#.00");
return Double.parseDouble(df.format(operatorUtils.mySqrt(getVarianceValue(list))));
}
/**
* 6-6号算子:公式计算器之样本标准偏差
* 标准差σ=sqrt(s^2),即标准差=方差的平方根
* @return 样本标准偏差 标准差
*/
public static Double getSampleStandardDeviationValue(List<Double> list){
OperatorUtils operatorUtils = new OperatorUtils();
DecimalFormat df = new DecimalFormat("#.00");
return Double.parseDouble(df.format(operatorUtils.mySqrt(getSampleVarianceValue(list))));
}
/**
* 7号算子:逻辑表达式
*/
public static List<Map<String,Boolean>> getLogicValue(List<String> list) {
List<Map<String,Boolean>> resultList = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
HashMap<String,Boolean> hashMap = new HashMap<>();
try{
OperatorUtils operatorUtils = new OperatorUtils();
Boolean cycleNumber = operatorUtils.parseBoolExpr(list.get(i));
hashMap.put(list.get(i),cycleNumber);
}finally {
}
resultList.add(hashMap);
}
return resultList;
}
/**
* 7号算子所用方法,用于返回布尔表达式的运算结果
* @param exp
* @return
*/
String exp;
int start;
private boolean parseBoolExpr(String expression) {
this.exp = expression;
this.start = 0;
try {
return doParse();
} finally {
this.exp = null;
}
}
/**
* 7号算子所用方法,用于计算布尔表达式的运算结果
* @param
* @return
*/
private boolean doParse() {
char c = exp.charAt(start);
switch (c) {
case 't':
return true;
case 'f':
return false;
case '&':
case '|':
case '!':
assert exp.charAt(start + 1) == '(';
break;
default:
assert false;
}
start += 2;
// !(t), !(f)
if (c == '!') {
try {
return !doParse();
} finally {
start++;
assert exp.charAt(start) == ')';
}
}
// &(....) |(.....)
boolean s = c == '&';
while (start < exp.length()) {
if (c == '&') {
s &= doParse();
} else {
s |= doParse();
}
start++;
if (exp.charAt(start) == ')') {
break;
}
assert exp.charAt(start) == ',';
start++;
}
return s;
}
/**
* 8号算子,变化速率
*/
// public static List<Map<String,Double>> getRateValue(List<Map<String,Double>> list){
// List<Map<String,Double>> resultList = new ArrayList<>();
// for (int i = 0; i < list.size(); i++) {
// HashMap<String,Double> hashMap = new HashMap<>();
// Map<String,Double> map = list.get(i);
// Double rate = (map.get("s1")-map.get("s0"))/(map.get("t1")-map.get("t0"));
// hashMap.put(map.toString(),rate);
// resultList.add(hashMap);
// }
// return resultList;
// }
//8号算子-变化速率
public static double getRateValue(List<Map<String, String>> list) {
List<Double> startList = new ArrayList<>();
List<Double> endList= new ArrayList<>();
double startSecond=0.0,endSecond=0.0;
for (int i = 0; i < list.size(); i++) {
HashMap<String,Double> hashMap = new HashMap<>();
Map<String,String> map = list.get(i);
//获取开始时间
String start = map.get("start");
//获取结束时间
String end = map.get("end");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
double d = Double.valueOf(map.get("value"));
endList.add(d);
try {
startSecond = sdf.parse(start).getTime();
endSecond = sdf.parse(end).getTime();
startList.add(startSecond);
endList.add(endSecond);
} catch (ParseException e) {
e.printStackTrace();
}
}
double[] doubles = new double[endList.size()];
for (int i = 0; i < endList.size(); i++) {
doubles[i] = endList.get(i);
}
Arrays.sort(doubles);
//将开始时间集合放到数组内
double [] starts = new double[startList.size()];
for(int i=0;i<startList.size();i++){
starts[i] = startList.get(i);
}
//开始时间数组
Arrays.sort(starts);
//将结束时间集合放到数组内
double [] ends = new double[endList.size()];
for(int i=0;i<endList.size();i++){
ends[i] = endList.get(i);
}
//结束时间数组
Arrays.sort(ends);
//获取开始值
double s0 = doubles[0];
//获取结束值
double s1 = doubles[doubles.length - 1];
//获取开始时间
double t0 = starts[0];
//获取结束时间
double t1 = ends[ends.length-1];
double rate = (s1 - s0) / (t1 - t0);
System.out.println(list);
return rate;
}
}