Get rid of complex logical calculations and get Aviator

Posted by praeses on Sun, 27 Feb 2022 13:05:45 +0100

Hello, everyone. I'm your good friend - Xiaofeng^

Introduction to Aviator

Aviator is a high-performance and lightweight expression evaluation engine implemented in java language, which is mainly used for dynamic evaluation of various expressions. Now there are many open source java expression evaluation engines available. Why do you need Aviator?

The implementation idea of aviator is very different from other lightweight evaluators. Other evaluators generally run by interpretation, while Aviator directly compiles expressions into Java bytecode and gives them to the JVM for execution. In short, aviator is positioned between a heavyweight scripting language such as Groovy and a lightweight expression engine such as ikeexpression.

Aviator feature

  • Most operators are supported, including arithmetic operator, relational operator, logical operator, bit operator, regular matching operator (= ~), ternary expression?:, It also supports the priority of operators and the mandatory priority of parentheses. For details, see the list of operators later.
  • Support function calls and custom functions
  • Support regular expression matching, which is similar to the matching syntax of ruby and Perl, and support Ruby like $digit to point to matching groups.
  • Automatic type conversion: when an operation is performed, the operand type will be automatically determined and converted accordingly. If it cannot be converted, an exception will be thrown.
  • It supports incoming variables and nested variable access similar to a.b.c.
  • Lightweight, high performance

Maven dependency

<dependency>
      <groupId>com.googlecode.aviator</groupId>
      <artifactId>aviator</artifactId>
      <version>5.2.3</version>
 </dependency>

Starting from version 3.2.0, Aviator only supports JDK 7 and above. JDK 6 please use the stable version of 3.1.1.

Usage scenario of Aviator

Execute expression

Aviator is used centrally through COM googlecode. aviator. Aviatorevaluator is handled by this entry class.

  • Aviator supports common arithmetic operators, including + - * /% five binary operators and unary operator - (negative).
  • Where - * /% and unary - can only act on Number type.
  • +It can be used not only for Number type, but also for the addition of String or the addition of String and other objects.
  • Aviator specifies that any type is added to String and the result is String.
  • The numeric type of Aviator only supports Long and Double. Any integer will be converted to Long and any floating-point number will be converted to Double, including the variable value passed in by the user.
import com.googlecode.aviator.AviatorEvaluator;

/**
 * @author Xiaofeng
 * @date 2022/2/24
 */
public class AviatorEvaluatorUtil {

    public static void main(String[] args) {
        Long result = (Long) AviatorEvaluator.execute("1+2+3");
        System.out.println(result);
    }
}

Operation result:

6

Compile expression

The examples mentioned above are all expressions executed directly. In fact, Aviator has done the compilation and execution work for you. You can compile the expression yourself, return a compiled result, and then pass in different env s to reuse the compiled results and improve the performance. This is the more recommended way to use

import com.googlecode.aviator.AviatorEvaluator;

import java.util.HashMap;
import java.util.Map;

/**
 * @author Xiaofeng
 * @date 2022/2/24
 */
public class AviatorEvaluatorUtil {

    public static void main(String[] args) {
        Map<String, Object> env2 = new HashMap<>(16);
        env2.put("a2", 10.1);
        env2.put("b2", 0.1);
        env2.put("c2", 0.1);
        String expression2 = "a2+b2-c2";
        Double result2 = (Double) AviatorEvaluator.execute(expression2, env2, true);
        System.out.println(result2);

        Map<String, Object> env3 = new HashMap<>(16);
        env3.put("a3", "xiao");
        env3.put("b3", "xiao");
        env3.put("c3", "feng");
        String expression3 = "a3+b3+c3";
        String result3 = AviatorEvaluator.execute(expression3, env3, true).toString();
        System.out.println(result3);
    }
}

Operation result:

10.1
xiaoxiaofeng

Call function

Aviator supports function calls. The style of function calls is similar to lua

import com.googlecode.aviator.AviatorEvaluator;

/**
 * @author Xiaofeng
 * @date 2022/2/24
 */
public class AviatorEvaluatorUtil {

    public static void main(String[] args) {
        System.out.println(AviatorEvaluator.execute("string.length('xiaoxiaofeng')"));
        System.out.println(AviatorEvaluator.execute("string.substring('xiaoxiaofeng',0,4)"));
        System.out.println(AviatorEvaluator.execute("string.contains(\"xiaoxiaofeng\",\"feng\")"));
        System.out.println(AviatorEvaluator.execute("string.contains(\"xiaoxiaofeng\",string.substring('xiaoxiaofeng',1,3))"));
    }
}

Operation result:

12
xiao
true
true

Accessing arrays and collections

You can access arrays and Java. Net files through brackets util. List object, you can use map Key to access Java util. value corresponding to key in map

import com.googlecode.aviator.AviatorEvaluator;

import java.util.*;


/**
 * @author Xiaofeng
 * @date 2022/2/24
 */
public class AviatorEvaluatorUtil {

    public static void main(String[] args) {

        List<String> list = new ArrayList<>();
        list.add("xiao");
        list.add(" feng");

        int[] array = new int[3];
        array[0] = 1;
        array[1] = 2;
        array[2] = 3;

        final Map<String, Date> map = new HashMap<>();
        map.put("date", new Date());

        Map<String, Object> env = new HashMap<>();
        env.put("list", list);
        env.put("array", array);
        env.put("dateMap", map);

        System.out.println(AviatorEvaluator.execute(
                "list[0]+list[1]+';array[0]+array[1]+array[2]='+(array[0]+array[1]+array[2]) +';today is '+dateMap.date ", env));
    }
}

Operation result:

xiao feng;array[0]+array[1]+array[2]=6;today is Fri Feb 25 15:24:10 CST 2022

ternary operator

Aviator does not provide if else statement, but provides ternary operator?:, bool? exp1: exp2. bool must be an expression of Boolean type, while Exp1 and exp2 can be any legal Aviator expression, and the result types returned by Exp1 and exp2 are not required to be the same.

import com.googlecode.aviator.AviatorEvaluator;

/**
 * @author Xiaofeng
 * @date 2022/2/24
 */
public class AviatorEvaluatorUtil {

    public static void main(String[] args) {
        Map<String, Object> env4 = new HashMap<>();
        env4.put("a", 1);
        String result = (String) AviatorEvaluator.execute("a>0? 'yes':'no'", env4);
        System.out.println(result);

    }
}

Operation result:

yes

Logical and relational operators

The logical operators supported by Aviator include the unary negative operator!, And logical and &, logical or. The operand of a logical operator can only be Boolean.

The relational operators supported by Aviator include <, < =, >, > =, = =,! =.

Relational operators can be used to compare the relationship between numbers, strings, patterns, Boolean, variables and other types and nil. Different types cannot be compared with each other except nil.

import com.googlecode.aviator.AviatorEvaluator;


/**
 * @author Xiaofeng
 * @date 2022/2/24
 */
public class AviatorEvaluatorUtil {

    public static void main(String[] args) {
        System.out.println(AviatorEvaluator.execute("(1>0||0<1)&&1!=0"));
    }
}

Operation result:

true

Bitwise Operators

Aviator supports all Java bitwise operators, including &, |, ^, ~, > >, <, > >.

import com.googlecode.aviator.AviatorEvaluator;

/**
 * @author Xiaofeng
 * @date 2022/2/24
 */
public class AviatorEvaluatorUtil {

    public static void main(String[] args) {
        System.out.println(AviatorEvaluator.execute("10<<2"));
        System.out.println(AviatorEvaluator.execute("100>>>2"));

    }
}

Operation result:

40
25

Operator list

Aviator supports the priority of operators and allows you to force the priority through parentheses. The following is a complete list of operators, in order of priority from high to low

Serial numberOperatorAssociativityOperand limit
0() [ ]From left to right() for function calls, [] for arrays and Java util. The element access of list requires that the index in [indx] must be an integer
1! -Right to left! Can be used for Boolean, - can only be used for Number
2* / %From left to rightBetween Number
3+ -From left to right+- can be used between numbers, + can also be used between strings, or between strings and other objects
4< <= > >=From left to rightBetween Number, String, Pattern, variable, other types and nil
5== != =~From left to right==And= It works between numbers, strings, patterns, variables, other types and nil, and between String and Java util. Between date, = ~ can only work between String and Pattern
6&&From left to rightShort circuit between Boolean
7||From left to rightShort circuit between Boolean
8? :Right to leftThe result of the first operand must be Boolean, and the results of the second and third operands are unlimited

Built in function

Function nameexplain
sysdate()Returns the current date object Java util. Date
rand()Returns a random number between 0 and 1, of type double
print([out],obj)Print the object. If out is specified, print to out, otherwise output to the console
println([out],obj)Similar to print, but wrap after output
now()Return to system currentTimeMillis
long(v)Change the type of the value to long
double(v)Change the value type to double
str(v)Change the type of the value to string
date_to_string(date,format)Convert the Date object into a string in a specific format. New in 2.1.1
string_to_date(source,format)Convert a string in a specific format into a Date object, new in 2.1.1
string.contains(s1,s2)Judge whether s1 contains s2 and return Boolean
string.length(s)Find the length of the string and return Long
string.startsWith(s1,s2)Whether s1 starts with s2 and returns Boolean
string.endsWith(s1,s2)Whether s1 ends with s2 and returns Boolean
string.substring(s,begin[,end])Intercept the string s from begin to end. If end is ignored, it will be from begin to end, which is the same as Java util. String. Substring.
string.indexOf(s1,s2)s1.0 in java Indexof (s2), find the starting index position of s2 in s1. If it does not exist, it is - 1
string.split(target,regex,[limit])String in Java The split method is the same, and a new function is added in 2.1.1
string.join(seq,seperator)Connect the elements in the set seq with seperator s as intervals to form a string. 2.1.1 adds a new function
string.replace_first(s,regex,replacement)String in Java Replacefirst method, added in 2.1.1
string.replace_all(s,regex,replacement)String in Java Replaceall method, 2.1.1 NEW
math.abs(d)Find the absolute value of d
math.sqrt(d)Find the square root of d
math.pow(d1,d2)Find the power d2 of d1
math.log(d)Find the natural logarithm of d
math.log10(d)Find the logarithm of d Based on 10
math.sin(d)Sine function
math.cos(d)cosine function
math.tan(d)Tangent function
map(seq,fun)Apply the function fun to each element of the set seq and return the set composed of new elements
filter(seq,predicate)Act the predicate on each element of the set and return the set composed of elements with the predicate true
count(seq)Returns the collection size
include(seq,element)Judge whether the element is in the set seq and return the boolean value
sort(seq)Sort collection, which is only valid for arrays and lists, and returns a new collection after sorting
reduce(seq,fun,init)fun receives two parameters. The first is the set element and the second is the cumulative function. This function is used to act on each element and initial value of the set and return the final init value
seq.eq(value)Returns a predicate used to determine whether the passed in parameter is equal to value. It is used for filter functions, such as filter(seq,seq.eq(3)). Filter returns a set of elements equal to 3
seq.neq(value)And SEQ Similar to EQ, it returns the predicate that determines that it is not equal to
seq.gt(value)Returns a predicate that determines whether it is greater than value
seq.ge(value)Returns a predicate that determines whether it is greater than or equal to value
seq.lt(value)Returns the predicate that determines whether it is less than value
seq.le(value)Returns the predicate that determines whether it is less than or equal to value
seq.nil()Returns the predicate that determines whether it is nil
seq.exists()Returns a predicate judged not to be nil

About me

I am Xiaofeng who only has great dreams and is extraordinary. I like writing and making friends

Let's hurry and grab me. Click on the bottom of my WeChat official account. 2022, we will progress together ~ ~

Topics: Java perl