java常用算子

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;
    }
}

测试结果

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值