对于一个学校项目,我被要求用Java编写一个简单的数学解析器。该程序工作正常。我用NetBeans profiler工具检查程序的性能非常好。为此,我对以下表达式的数学解析器进行了1000次调用循环:"1-((x+1)+1)*2"
,其中x
被当前循环计数替换。花了262ms
。问题是,在方法splitFormula中占用了50%的时间,我将在下面介绍:
private static void splitFormula(String formula){
partialFormula=new ArrayList<>();
for(String temp: formula.split("\\+|\\-|\\*|\\/"))
partialFormula.add(temp);
}
,其中partialFormula是一个ArrayList
的字符串。为了数值计算表达式,我需要多次调用splitFormula方法,所以我真的需要清除partialFormula ArrayList
- 第一行的内容。
我的问题是:是否有更快的方法来分割字符串然后将部分字符串添加到arraylist?或者是否有其他方法可用于拆分字符串然后使用子字符串?
答案 0 :(得分:7)
正则表达式可以减慢速度(String#split
使用正则表达式)。一般来说,如果你想编写简单的代码,正则表达式是好的,但如果你想要快速代码,看看是否有另一种方式。尝试不使用正则表达式执行此操作:
编辑:这应该是一种更好的方法(跟踪索引而不是附加到StringBuilder
):
private static void splitFormula(String formula){
partialFormula.clear(); // since there is a method for this, why not use it?
int lastIndex = 0;
for (int index = 0; index < formula.length(); index++) {
char c = formula.charAt(index);
if (c == '-' || c == '+' || c == '*' || c == '/') {
partialFormula.add(formula.substring(lastIndex, index));
lastIndex = index + 1; //because if it were index, it would include the operator
}
}
partialFormula.add(formula.substring(lastIndex));
}
StringBuilder
方法:
private static void splitFormula(String formula){
partialFormula.clear();
StringBuilder newStr = new StringBuilder();
for (int index = 0; index < formula.length(); index++) {
char c = formula.charAt(index);
if (c == '-' || c == '+' || c == '*' || c == '/') {
partialFormula.add(newStr.toString());
newStr.setLength(0);
} else {
newStr.append(c);
}
}
partialFormula.add(newStr.toString());
}
如果我们查看String#split
的源代码,很明显为什么那么慢(来自GrepCode):
public String[] split(String regex, int limit) {
return Pattern.compile(regex).split(this, limit);
}
每次编译一个正则表达式!因此,我们可以看到加速代码的另一种方法是首先编译我们的正则表达式,然后使用Pattern#split
进行拆分:
//In constructor, or as a static variable.
//This regex is a better form of yours.
Pattern operatorPattern = Pattern.compile("[-*+/]");
...
private static void splitFormula(String formula){
partialFormula.clear();
for(String temp: operatorPattern.split(formula)) {
partialFormula.add(temp);
}
}
答案 1 :(得分:0)
您不需要for
循环。 split
返回一个数组,您可以从数组中创建ArrayList
:
partialFormula = new ArrayList<>(Arrays.asList(formula.split("\\+|\\-|\\*|\\/")));
这是否明显更快,我不知道。
答案 2 :(得分:0)
请事先预先分配ArrayList,这样我们就不必在列表增长时支付重新分配费用。下面的20
数字只是一个占位符。选择一个比你期望的最大表达式大一点的数字。
partialFormula=new ArrayList<String>(20);
请参阅this question,了解这可能会给您带来什么。
答案 3 :(得分:0)
这将创建一个字符串数组列表。
String a= "1234+af/d53";
char [] blah=a.toCharArray();
ArrayList<String> list=new ArrayList<String>();
for (int i = 0; i < blah.length; i++) {
list.add(Character.toString(blah[i]));
}