2011-08-18 100 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提及實習。 –