2011-08-18 76 views
4

我有发动机的方法我使用(andengine):字符串和垃圾收集

public final void setText(String pString){...} 

我的应用程序更新每1秒从静止INT

mScoreText.setText(""+PlayerSystem.mScore); 

问题得分是这每隔一秒创建一个新的String对象,并在1分钟后,我有59个字符串对象通过GC和其他AbstractStringBuilders和init收集...

我找到了andeng的部分解决方案INE论坛这样的:

private static StringBuilder mScoreValue = new StringBuilder("000000"); 

private static final char[] DIGITS = {'0','1','2','3','4','5','6','7','8','9'}; 

mScoreValue.setCharAt(0, DIGITS[(PlayerSystem.mScore% 1000000)/100000]); 
mScoreValue.setCharAt(1, DIGITS[(PlayerSystem.mScore% 100000)/10000]); 
mScoreValue.setCharAt(2, DIGITS[(PlayerSystem.mScore% 10000)/1000]); 
mScoreValue.setCharAt(3, DIGITS[(PlayerSystem.mScore% 1000)/100]); 
mScoreValue.setCharAt(4, DIGITS[(PlayerSystem.mScore% 100)/10]); 
mScoreValue.setCharAt(5, DIGITS[(PlayerSystem.mScore% 10)]); 
mScoreText.setText(mScoreValue.toString()); 

但主要问题仍然存在,的ToString()将返回新对象每次调用

有什么办法解决?

+1

你真的关心每个*秒*一个字符串吗?这对我来说似乎并不多,特别是因为我期望每次点击或其他事件都会创建一个新的(事件)对象。 –

+2

是的。停止关心。垃圾收集器足够快,以至于每秒一次分配的担心完全是惊人的,不成比例。这种毫无意义的小提琴工作就是计算机最擅长的 - 让他们这样做,并利用你的智力来获得更有价值的东西。 –

+0

使用该代码将是严重的过早优化的情况。我认为最后所有的模操作,分区,从数组中提取数据和设置字符都会比一次创建字符串和相关的垃圾回收花费更多的处理时间。就像其他人指出的那样,最后你用toString()创建了一个String。如果您正在处理这样的限制,即每分钟分配60个小对象太多,那么Java并不是您想要使用的语言。 C或装配将更接近该商标。 –

回答

3

据我所知,没有办法解决Strings是不可变的事实,如果你的方法需要一个字符串,每次都必须创建一个新的字符串。

+0

好吧,人们可以玩反射,并获得更高的性能打击,但是,基本上就是这样。每秒一个小物件?懒得无趣。 – Voo

+1

我同意这不是一个真正的大问题,但我认为有责任心的程序员应该意识到这些问题,而不是仅仅说'不用担心,编译器会照顾它'。它表现出对能力的兴趣和对你的工艺的热爱。 –

+0

@Russ C我不同意。对于任何优化而言,最重要的事情就是要知道最多可以赢得多少。 。我敢打赌,如果他想剖析代码,他甚至不会注意到它。在地狱里没有机会,这会在时机上产生任何影响。 (并相信我至少对于javac而言,我确切知道它会为字符串连接生成哪些代码 - 如果没有循环或函数调用,忘记它是一个很好的规则) – Voo

3

这听起来像一个很好的候选人,以使用StringBuilder:

http://developer.android.com/reference/java/lang/StringBuilder.html

或者StringBuffer的:

http://developer.android.com/reference/java/lang/StringBuffer.html

推理是:

StringBuffer的用于存储字符的字符串将被改变(字符串对象不能改变)。它会根据需要自动扩展。相关类:String,CharSequence。

StringBuilder是在Java 5中添加的。它在各方面都与StringBuffer相同,只是它不同步,这意味着如果多个线程同时访问它,可能会有麻烦。对于单线程程序,最常见的情况是,避免同步的开销使得StringBuilder的速度稍快。

编辑: 你必须要注意的一件事是你如何使用你选择的SB类。 原因是(在.net中同样也是如此),如果你有这样

StringBuilder sb = new StringBuilder(score.ToString() + "hello, world!"); 

一个使用你还有2个字符串连接操作,你可能实际进行3串那里,一个score.ToString(),一个将文字"hello, world!"转换为一个字符串,并将两个连接在一起。 为了获得最佳效果,您需要使用SB的追加/插入/替换方法。

+1

它们比“”+ int更快,但以相同数量的对象结束 – SJuan76

+1

他仍然必须调用'toString'方法,该方法仍然会创建一个新的字符串对象,所以问题仍然存在。 – Daniel

+0

@ SJuan76由于创建StringBuilder或StringBuffer类的开销,StringBuilder甚至不会比“”+ int更快。它们确实只适用于在循环中修改字符串一些不确定的次数。 – Daniel

2

首先,两分钟内有120个物体是你应该担心的,除非它们非常大。

其次,String类包含所有创建的字符串池。所以,如果你做

String a = new String("Nabucodonosor King of Babilonia"); 
String b = new String("Nabucodonosor King of Babilonia"); 

然后Nabucodonosor King of Babilonia只存储一次在内存中(但也有它指向两个String对象)。详细信息请参阅String#intern()。

最后,正如Daniel指出的那样,由于字符串是不可变的,所以没有使用字符串的解决方法。你可以做一些技巧(使用旧值检查新值,只有在不同的情况下创建字符串),但我怀疑他们补偿了增加的复杂性。

+0

+1提及实习。 –