作为笔记,直接上代码
IntervalUtil
package com.utils;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
public class IntervalUtil {
public static ScriptEngine jse = new ScriptEngineManager().getEngineByName("JavaScript");
/**
* @Description: 比较dataValue与interval结果
* @Param: [dataValue:比较值, interval:如 ≤0、≥0 、>0 、<0 、==0]
* @return: boolean
*/
public static boolean compareNumValue(String dataValue,String interval) {
//转换比较符号≤转换为<=,≥转换为>=
String comparator = interval.replace("≤", "<=").replace("≥", ">=");
//拼接表达式
StringBuffer formula = new StringBuffer();
formula.append("(");
formula.append(dataValue);
formula.append(comparator);
formula.append(")");
try {
//计算表达式
return (Boolean) jse.eval(formula.toString());
} catch (Exception t) {
return false;
}
}
/**
* 判断data_value是否在interval区间范围内
* @param data_value 数值类型的
* @param interval 正常的数学区间,包括无穷大等,如:(1,3)、>5%、(-∞,6]、(125%,135%)U(70%,80%)
* @return true:表示data_value在区间interval范围内,false:表示data_value不在区间interval范围内
*/
public static boolean isInTheInterval(String data_value,String interval) {
//将区间和data_value转化为可计算的表达式
String formula = getFormulaByAllInterval(data_value,interval,"||");
ScriptEngine jse = new ScriptEngineManager().getEngineByName("JavaScript");
try {
//计算表达式
return (Boolean) jse.eval(formula);
} catch (Exception t) {
return false;
}
}
public static String eval(String el){
try {
return new DecimalFormat("0.00").format(jse.eval(el));
} catch (ScriptException e) {
e.printStackTrace();
return "0.00";
}
}
/**
* 将所有阀值区间转化为公式:如
* [75,80) =》 date_value < 80 && date_value >= 75
* (125%,135%)U(70%,80%) =》 (date_value < 1.35 && date_value > 1.25) || (date_value < 0.8 && date_value > 0.7)
* @param date_value
* @param interval 形式如:(125%,135%)U(70%,80%)
* @param connector 连接符 如:") || ("
*/
private static String getFormulaByAllInterval(String date_value, String interval, String connector) {
StringBuffer buff = new StringBuffer();
for(String limit:interval.split("U")){//如:(125%,135%)U (70%,80%)
buff.append("(").append(getFormulaByInterval(date_value, limit," && ")).append(")").append(connector);
}
String allLimitInvel = buff.toString();
int index = allLimitInvel.lastIndexOf(connector);
allLimitInvel = allLimitInvel.substring(0,index);
return allLimitInvel;
}
/**
* 将整个阀值区间转化为公式:如
* 145) =》 date_value < 145
* [75,80) =》 date_value < 80 && date_value >= 75
* @param date_value
* @param interval 形式如:145)、[75,80)
* @param connector 连接符 如:&&
*/
private static String getFormulaByInterval(String date_value, String interval, String connector) {
StringBuffer buff = new StringBuffer();
for(String halfInterval:interval.split(",")){//如:[75,80)、≥80
buff.append(getFormulaByHalfInterval(halfInterval, date_value)).append(connector);
}
String limitInvel = buff.toString();
int index = limitInvel.lastIndexOf(connector);
limitInvel = limitInvel.substring(0,index);
return limitInvel;
}
/**
* 将半个阀值区间转化为公式:如
* 145) =》 date_value < 145
* ≥80% =》 date_value >= 0.8
* [130 =》 date_value >= 130
* <80% =》 date_value < 0.8
* @param halfInterval 形式如:145)、≥80%、[130、<80%
* @param date_value
* @return date_value < 145
*/
private static String getFormulaByHalfInterval(String halfInterval, String date_value) {
halfInterval = halfInterval.trim();
if(halfInterval.contains("∞")){//包含无穷大则不需要公式
return "1 == 1";
}
StringBuffer formula = new StringBuffer();
String data = "";
String opera = "";
if(halfInterval.matches("^([<>≤≥\\[\\(]{1}(-?\\d+.?\\d*\\%?))$")){//表示判断方向(如>)在前面 如:≥80%
opera = halfInterval.substring(0,1);
data = halfInterval.substring(1);
}else{//[130、145)
opera = halfInterval.substring(halfInterval.length()-1);
data = halfInterval.substring(0,halfInterval.length()-1);
}
double value = dealPercent(data);
formula.append(date_value).append(" ").append(opera).append(" ").append(value);
String a = formula.toString();
//转化特定字符
return a.replace("[", ">=").replace("(", ">").replace("]", "<=").replace(")", "<").replace("≤", "<=").replace("≥", ">=");
}
/**
* 去除百分号,转为小数
* @param str 可能含百分号的数字
* @return
*/
private static double dealPercent(String str){
double d = 0.0;
if(str.contains("%")){
str = str.substring(0,str.length()-1);
d = Double.parseDouble(str)/100;
}else{
d = Double.parseDouble(str);
}
return d;
}
public static boolean isOverlap(List<String> laplist){
List<ReqRespResearchProductQuestionnaireItem> list = new ArrayList<>();
for (String lap:laplist
) {
list.add(convertlaps(lap));
}
return SectionUtil.compareSection(list);
}
public static ReqRespResearchProductQuestionnaireItem convertlaps(String lap){
// 7-全闭区间/8-左闭右开区间/9-左开右闭区间/10-全开区间
String min = "";
String max = "";
String el = "";
el = String.valueOf(lap.charAt(0))+ String.valueOf(lap.charAt(lap.length()-1));
Byte type = new Byte("0");
if(el.equals("[]")){
type = new Byte("7");
}
else if(el.equals("[)")){
type = new Byte("8");
}
else if(el.equals("(]")){
type = new Byte("9");
}
else if(el.equals("()")){
type = new Byte("10");
}else{
throw new RuntimeException("区间表达式格式异常------->"+ lap);
}
String[] s1s = lap.split(",");
min = s1s[0].substring(1);
max = s1s[1].substring(0,s1s[1].length()-1);
System.out.println(min+"---"+max+"---"+el+"-- 7-全闭区间/8-左闭右开区间/9-左开右闭区间/10-全开区间 --"+type);
return new ReqRespResearchProductQuestionnaireItem(min,max,type);
}
public static void main(String[] args) {
IntervalUtil a = new IntervalUtil();
//无穷小
//System.out.println(a.isInTheInterval("5", "(-∞,6]"));
//判断区间范围
System.out.println(a.isInTheInterval("3.1", "(1,3]"));
//比较dataValue与interval结果
String eval = "≥0";
System.out.println(a.compareNumValue("5", eval));
eval = "(2*2*2*2)/3-2";
System.out.println(eval(eval));
String s1 = "(0.23,90.88]";
convertlaps(s1);
String el = "(2>1)&&(3<2)";
String el1 = "(#score>1)||(#check_status<2)";
String el2 = "(1,2) U (2,5)U (3,10)";
try {
System.out.println("el-------------->"+ jse.eval(el));
System.out.println("el-------------->"+ ElUtil.pick(el1));
System.out.println(a.isInTheInterval("13.1", el2));
} catch (ScriptException e) {
throw new RuntimeException(e);
}
}
}
ReqRespResearchProductQuestionnaireItem
package com.utils;
import java.io.Serializable;
public class ReqRespResearchProductQuestionnaireItem implements Serializable {
private String minValue;
private String maxValue;
//"范围符号:1-大于/2-小于/3-等于/4-不等于/5-大于等于/6-小于等于/7-全闭区间/8-左闭右开区间/9-左开右闭区间/10-全开区间"
private Byte symbol;
public ReqRespResearchProductQuestionnaireItem( String minValue, String maxValue, Byte symbol) {
this.minValue = minValue;
this.maxValue = maxValue;
this.symbol = symbol;
}
public String getMinValue() {
return minValue;
}
public void setMinValue(String minValue) {
this.minValue = minValue;
}
public String getMaxValue() {
return maxValue;
}
public void setMaxValue(String maxValue) {
this.maxValue = maxValue;
}
public Byte getSymbol() {
return symbol;
}
public void setSymbol(Byte symbol) {
this.symbol = symbol;
}
}
SectionUtil
package com.utils;
import com.alibaba.fastjson.JSONObject;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
public class SectionUtil {
//最小值
private String min_entity;
//最大值
private String max_entity;
//左侧括号状态:false -开区间 true-- 闭区间
private boolean left_sate = false;
//右侧括号状态:false -开区间 true-- 闭区间
private boolean right_sate = false;
private SectionUtil() {
}
public SectionUtil(String min_entity, String max_entity, boolean left_sate, boolean right_sate) {
this.min_entity = min_entity;
this.max_entity = max_entity;
this.left_sate = left_sate;
this.right_sate = right_sate;
}
public String getMin_entity() {
return min_entity;
}
public String getMax_entity() {
return max_entity;
}
public boolean isLeft_sate() {
return left_sate;
}
public boolean isRight_sate() {
return right_sate;
}
/**
* @description: 创建负区间((负无穷,X])
* @param value 区间最大值
* @param right_sate 区间开闭状态
*
*/
public static SectionUtil creatFu(String value, boolean right_sate) {
return new SectionUtil("", value, false, right_sate);
}
/**
* @description: 创建正区间[X,正无穷))
* @param value 区间最小值
* @param left_sate 区间开闭状态
*
*/
public static SectionUtil creatZheng(String value, boolean left_sate) {
return new SectionUtil(value, "", left_sate, false);
}
/**
* @description: 创建闭合区间([X,Y])
* @param min 区间最小值
* @param max 区间最大值
* @param left_sate 区间左侧开闭状态
* @param right_sate 区间右侧开闭状态
* @return
*
*/
public static SectionUtil creat(String min, boolean left_sate, String max, boolean right_sate) {
return new SectionUtil(min, max, left_sate, right_sate);
}
/**
* @description: 将实体类转换成区间集合
* @param record 待转换的实体类
* @return 转换后的区间集合类(不等于时转换后为2个区间,所以采用集合)
*
*/
public static List<SectionUtil> getSections(ReqRespResearchProductQuestionnaireItem record) {
List<SectionUtil> list = new ArrayList<>();
String record_max = record.getMaxValue();
String record_min = record.getMinValue();
switch (record.getSymbol()) {
case 1:
list.add(creatZheng(record_max, false));
break;
case 2:
list.add(creatFu(record_max, false));
break;
case 3:
list.add(creat(record_max, true, record_max, true));
break;
case 4:
list.add(creatFu(record_max, false));
list.add(creatZheng(record_max, false));
break;
case 5:
list.add(creatZheng(record_max, true));
break;
case 6:
list.add(creatFu(record_max, true));
break;
case 7:
list.add(creat(record_min, true, record_max, true));
break;
case 8:
list.add(creat(record_min, true, record_max, false));
break;
case 9:
list.add(creat(record_min, false, record_max, true));
break;
case 10:
list.add(creat(record_min, false, record_max, false));
break;
}
return list;
}
public int compareTo(String first_value, String second_value) {
//first_value为空表示为正无穷,second_value为空表示为负无穷
if (isBlank(first_value) || isBlank(second_value)) {
return 1;
}
return compareToValue(first_value,second_value);
}
//判断字符串是否为空
public static boolean isBlank(String str) {
int strLen;
if (str == null || (strLen = str.length()) == 0) {
return true;
}
for (int i = 0; i < strLen; i++) {
if ((Character.isWhitespace(str.charAt(i)) == false)) {
return false;
}
}
return true;
}
/**
* @param record 判断区间是否有重合
* @return true-有重合 false -无重合
* @description: 判断当前区间是否和指定区间重合
*
*/
public boolean isChonghe(SectionUtil record) {
String min_entity = record.getMin_entity();
String max_entity = record.getMax_entity();
boolean left_sate = record.isLeft_sate();
boolean right_sate = record.isRight_sate();
boolean left_isok = false;
boolean right_isok = false;
//重合条件,第一个区间最大值大于第二个区间最小值并且第一个区间的最小值小于第二个区间的最大值
//注意传值顺序,第一个值为第一个区间的最大值(此处不能反)
int first_result = compareTo(this.max_entity, min_entity);
if ((first_result == 0 && this.right_sate && left_sate) || (first_result > 0)) {
left_isok = true;
}
//注意传值顺序,第一个值为第二个区间的最大值(此处不能反)
int second_result = compareTo(max_entity, this.min_entity);
//此处本应该是second_result<0,但由于上一步参数传递时时反正传递,故此此处为second_result>0
if ((second_result == 0 && this.left_sate && right_sate) || second_result > 0) {
right_isok = true;
}
return left_isok && right_isok;
}
/**
* @description: 比较集合中区间是否有重叠
* @param list1 待比较集合1
* @param list2 待比较集合2
* @return
*
*/
public static boolean isChonghe(List<SectionUtil> list1, List<SectionUtil> list2) {
boolean chonghed = false;
for (SectionUtil item1 : list1) {
for (SectionUtil item2 : list2) {
chonghed = item1.isChonghe(item2);
if (chonghed) {
return true;
}
}
}
return chonghed;
}
//比较大小
public static int compareToValue(String value1, String value2) {
BigDecimal b1 = new BigDecimal(value1);
BigDecimal b2 = new BigDecimal(value2);
return b1.compareTo(b2);
}
/**
* @description: 判断集合中区间是否重叠
* @param list 待判断集合
* @return fasle-无重叠 true-有重叠
*
*/
public static boolean compareSection(List<ReqRespResearchProductQuestionnaireItem> list) {
for (int i = 0; i < list.size(); i++) {
ReqRespResearchProductQuestionnaireItem record = list.get(i);
for (int j = i + 1; j < list.size(); j++) {
ReqRespResearchProductQuestionnaireItem item = list.get(j);
//判断区间是否有交叉
List<SectionUtil> records = SectionUtil.getSections(record);
List<SectionUtil> items = SectionUtil.getSections(item);
boolean chonghe = SectionUtil.isChonghe(records, items);
if (chonghe) {
System.out.println(JSONObject.toJSONString(records));
System.out.println(JSONObject.toJSONString(items));
return true;
}
}
}
return false;
}
public static void main(String[] args) {
List<ReqRespResearchProductQuestionnaireItem> list = new ArrayList<>();
list.add(new ReqRespResearchProductQuestionnaireItem("1","5",new Byte("10")));
list.add(new ReqRespResearchProductQuestionnaireItem("5","10",new Byte("8")));
// list.add(new ReqRespResearchProductQuestionnaireItem("10","20",new Byte("9")));
// list.add(new ReqRespResearchProductQuestionnaireItem("20","2",new Byte("10")));
System.out.println(compareSection(list));
}
}
调用区间判断
List<String> laps = new ArrayList<>();
laps.add("[1,5]");
laps.add("[2,4]");
laps.add("[11,15]");
if(IntervalUtil.isOverlap(laps)){
throw new Exception("区间存在冲突") ;
}