我有这个代码来连接一些数组元素:
StringBuilder sb = new StringBuilder();
private RatedMessage joinMessage(int step, boolean isresult) {
sb.delete(0, sb.length());
RatedMessage rm;
for (int i = 0; i <= step; i++) {
if (mStack[i] == null)
continue;
rm = mStack[i].getCurrentMsg();// msg is built upfront, this just returns, it's a getter method call
if (rm == null || rm.msg.length() == 0)
continue;
if (sb.length() != 0) {
sb.append(", ");
}
sb.append(rm.msg);
}
rm.msg=sb.toString();
return rm;
}
重要的是,数组最多可容纳10个项目,所以它不是很多。
我的跟踪输出告诉我这个方法被称为18864次,16%的运行时间花在了这个方法上。我可以优化更多吗?
答案 0 :(得分:5)
首先,我不会重复使用StringBuilder并始终创建新实例。这肯定会更快,因为它允许GC使用年轻代堆区域。
允许消除至少一个if语句的另一个小技巧是重写你的代码:
String separator = "";
for (int i = 0; i <= step; i++) {
...
sb.append(separator);
sb.append(rm.msg);
separator = ", ";
}
答案 1 :(得分:3)
一些想法:
1)您是否使用估计的最大容量初始化StringBuilder?这可以节省内部阵列重新分配所花费的时间。复制。
2)也许你可以在循环中附加一个尾随逗号,并避免循环内字符串长度的条件。相反,在方法结束时添加单个条件,并在需要时删除尾随逗号。
答案 2 :(得分:1)
您可以进行以下更改(仅显示差异):
String separator = "";
for (int i = 0; i <= step; i++) {
// ...
sb.append(separator).append(rm.msg);
separator = ", ";
}
如果额外增加9次,则需要花费额外费用。在决定保留此更改之前,您应该测量它是否对您使用的数据有所帮助: - )
答案 3 :(得分:0)
如果您的函数应该连接数组元素,为什么要传递所有这些疯狂值和未使用的参数?
private string joinMessage( string[] myArray)
{
StringBuilder sbr = new StringBuilder();
for(int i = 0; i < myArray.Length; i++)
{
if(!string.IsNullOrEmpty(myArray[i])
{
sbr.Append(myArray[i]);
sbr.Append(",")
}
}
return sbr.ToString();
}
答案 4 :(得分:0)
首先逐步浏览堆栈中的每个元素,计算所有字符串长度的总和。
然后你可以使用
sb.ensureCapacity(totalEndLength);
字符串构建器的工作方式类似于数组列表,因此您可能正在使用大部分附加重建该数组。
答案 5 :(得分:0)
一点迷你优化......在循环之外使用test-for-comma。
private RatedMessage joinMessage(int step, boolean isresult) {
sb.delete(0, sb.length());
for (int i = 0; i <= step; i++) {
if (mStack[i] == null)
continue;
rm = mStack[i].getCurrentMsg();
if (rm == null || rm.msg.length() == 0)
continue;
sb.append(rm.msg).append(", ");
}
if (sb.length() > 2) {
sb.delete(sb.length() - 2, 2);
}
return sb.toString();
}
其他建议如下:
答案 6 :(得分:0)
使用字符串表示形式的mStack
数组的单独副本,默认情况下使用空字符串初始化,因此您的循环将是:
String [] mStackCopy = new String[]{"","","","","","","","","","",};
// or mstackCopy = new String[mStack.length];
// for( int i = 0 ; i < mStackCopy.lenght ; i++ ) { mStack[i] = "" }
另外,创建具有足够容量的StringBuilder:
StringBuilder sb = new StringBuilder( 10000 );// 10k chars or whatever makes sense.
因此,当您需要创建消息时,您只需:
for (int i = 0; i <= step; i++) {
sb.append( mStackCopy[i] );
}
空白部分不会导致问题,因为它们已经是空白的:
你甚至可以硬编码:
sb.append( mStackCopy[0]);
sb.append( mStackCopy[1]);
sb.append( mStackCopy[2]);
sb.append( mStackCopy[3]);
sb.append( mStackCopy[4]);
sb.append( mStackCopy[5]);
sb.append( mStackCopy[6]);
sb.append( mStackCopy[7]);
sb.append( mStackCopy[8]);
sb.append( mStackCopy[9]);
但是,这将导致更多的痛苦,而不是未来的救济,保证。
当您向mStack添加内容时:
MStack item = new MStack();
item.setCurrentMessage("Some message");
....
只需制作邮件的副本,然后附加“,”。
addToMStack(int position, MStackItem item ) {
mStack[position] = item;
mStackCopy[position] = item.getCurrentMessage() + ", ";
}
并且取决于空值的出现(如果它是低的)你可以捕捉它们
addToMStack(int position, MStackItem item ) {
if( item == null ) { return; }
mStack[position] = item;
try {
mStackCopy[position] = item.getCurrentMessage() + ", ";
} catch( NullPointerException npe ){}
}
可怕的
或验证它:
addToMStack(int position, MStackItem item ) {
if( item == null ) { return; }
mStack[position] = item;
mStackCopy[position] = item.getCurrentMessage() + ", ";
}
我很确定你的方法正在做一些你没有告诉我们的事情。原因可能就在那里。
另外,如果100%是1秒,则16%并不坏。
答案 7 :(得分:0)
如果您的mStack是Collection而不是数组,则可以执行mStack.toString()
,这将打印数组的可读字符串。这可能比写自己更容易。
答案 8 :(得分:0)
此方法的运行时间为16%,包括或,不包括被称为方法?如果getCurrentMsg()调用创建了大量对象,则它可能是一个隐藏的问题。
除此之外,我建议从你的堆栈中取出所有需要的字符串,然后调用
StringUtils.join(myStrings, ", ")
使用Apache commons library。尝试依靠经过测试的代码来处理这些低级别的事情,而不是每隔一天自己优化一次。最后,这将为您提供更好的优化结果,因为您将能够专注于整体情况(即软件的整体设计)。
答案 9 :(得分:0)
有时候没有什么可以优化的。我认为这是其中一种情况。你可以尝试削减一两条指令,但原则上你不会得到更快的速度。
我认为唯一要优化的是考虑为什么你将它称为18864次以及是否可以完全避免这些调用中的一些。也许有些不需要,或者你可以在某些情况下缓存结果。
答案 10 :(得分:0)
使用来自Apache Commons Lang的StringBuilder + StringUtils。通过带有分隔符的String循环和chomping是StringUtils的全部内容!
private RatedMessage joinMessage(int step, boolean isresult) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i <= step; i++) {
WhateverTypeIsFromMStackVariable stackVariable = mStack[i];
String message = getMessage(stackVariable);
if(StringUtils.isNotEmpty(message)) {
builder.append(message).append(", ");
}
}
RatedMessage rm = new RatedMessage();
rm.msg = StringUtils.chomp(builder.toString(), ", ");
return rm;
}
private static String getMessage(WhateverTypeIsFromMStackVariable stackVariable) {
if(stackVariable != null) {
RatedMessage message = stackVariable.getCurrentMsg();
if(message != null) {
return message.msg;
}
}
return null;
}
Apache Commons Lang在这里:http://commons.apache.org/lang/