一道关于优化的面试题,一家互联网公司的面试题

最近遇到一个有意思的面试题,关于优化的。

系统中有一个方法func,每10秒钟就会调用一次,性能有问题,请优化一下,主要考虑运行效率。方法如下。

LinkedList<Date> dates = new LinkedList<Date>();

……


public String func(String bits)
{
Random random = new Random(System.currentTimeMillis());

String str = "";
for(int i = 0; i < (bits.length() > 1000 ? bits.length() : 1000); ++i)
{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
str += sdf.format(dates.get(i));
}
return str;

}

可以看到,这个方法的作用就是将dates的元素按照List的顺序以一定的格式拼接在一起,拼接的元素总数以bits.length() > 1000 ? bits.length() : 1000得到。

我的优化方案:由于for循环里总是在做String的链接,这样会产生很多小的对象,而循环次数也不少,容易导致垃圾回收。String改为StringBuffer,这样就能避免产生小对象。看代码。

public String func1(String bits)
{
StringBuffer sb = new StringBuffer();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for(int i = 0; i < (bits.length() > 1000 ? bits.length() : 1000); ++i)
{
sb.append(sdf.format(dates.get(i)));
}
return sb.toString();
}

上面的就是我的面试答案。哎,只有更好,没有最好啊。

进一步,循环至少迭代1000次,那么,在某个步骤准备好一个字符串(datemat1000)。可如果dates发生变化,比如remove前面的对象,就会导致结果不正确。

再进一步,如果考虑到了remove的时候,变化这个datamat1000,那结果就正确。

有没有更好的方案呢,如果bits很长(相应的,dates肯定也长),还是会迭代很多次,效率还会有问题。

啊哈,灵光一闪,能否预先将dates所有的元素预先拼接在一起,在dates add和remove的时候将拼接的StringBuffer做出相应变化,在func里根据bits的长度从StringBuffer里复制字符串来。这样就不会再每10秒运行的func里有太多动作。缺点:remove(object o)这个方法里需要重新构建字符串。

请看代码:

MyLinkedList dates = new MyLinkedList();


//      ……
public String func2(String bits)
{
int bitlen = bits.length() > 1000 ? bits.length() : 1000;
return dates.getDatesSb().substring(0, bitlen * dates.SDF_LEN);
}



class MyLinkedList<Date> extends LinkedList<Date>{

private StringBuffer datesSb = new StringBuffer();
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public final int SDF_LEN = 19;
@Override
public boolean add(Date date)
{
boolean isok = super.add(date);
if(!isok)
return isok;
dateSb.append(sdf.format(date));
return isok;
}
private void reInit()
{
StringBuffer sb = new StringBuffer();
for(int i = 0; i < super.size(); i++)
{
sb.append(sdf.format(super.get(i)));
}
dateSb = sb;
}
@Override
public boolean remove(Object o)
{
boolean isok = super.remove(o);
if(!isok)
return isok;
reInit();
return isok;
}
@Override
public Date remove(int index)
{
Date date = super.remove(index);
if(date != null)
{
dateSb.delete(index* SDF_LEN, (index + 1) * SDF_LEN);
}
return date;
}
//……
public StringBuffer getDatesSb() {
return datesSb;
}

}



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值