在一个Android游戏中,我有一个循环,运行大约1500万次,在这个循环中,我会修改单词片段,并在字典中检查结果。我注意到很多GC调用,我的主要怀疑是StringBuilder.toString(),它总是创建一个新的字符串。
我在Java方面比较有经验,不知道如何避免这种分配,并以某种方式将内部char数组传递给包含(),而不需要任何分配或复制。
描述我的问题的简化伪代码片段:
static HashSet<String>dictionary; // loaded from text file
String[7] wordParts = new String[7]; // pre-filled from player data
StringBuilder sb = new StringBuilder(20);
for (i=15 million times) {
sb.setLength(0);
for (j=2-7 times) {
sb.append(wordParts[j]);
}
if (dictionary.contains(sb.toString()) {
processValidWord();
}
}发布于 2014-01-23 13:26:59
使用Pablo的建议:
static HashSet<DictionaryItem>dictionary; // loaded from text file
String[7] wordParts = new String[7]; // pre-filled from player data
DictionaryItem di = new DictionaryItem();
for (i=15 million times) {
di.setEmpty();
for (j=2-7 times) {
di.append(wordParts[j]);
}
if (dictionary.contains(di) {
processValidWord();
}
}从字符串和StringBuilder中窃取,但是为这个特殊的应用程序动态构建哈希代码:
public class DictionaryItem {
int hashCode;
int length;
char[] chars = new char[15];
public DictionaryItem(String initialValue) {
this();
append(initialValue);
}
public DictionaryItem() {
setEmpty();
}
public void setEmpty() {
hashCode = 0;
length = 0;
}
public void append(String s) {
for (int i=0;i<s.length();i++) {
chars[length++] = s.charAt(i);
hashCode = 31*hashCode + s.charAt(i);
}
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o instanceof DictionaryItem) {
DictionaryItem di = (DictionaryItem)o;
if (di.length == length) {
int i = length-1;
while (i >= 0) {
if (di.chars[i] != chars[i]) {
return false;
}
i--;
}
return true;
}
}
return false;
}
@Override
public int hashCode() {
return hashCode;
}
@Override
public String toString() {
return new String(chars, 0, length);
}
}现在搜索期间没有分配,toString()很少用于向用户显示结果。
发布于 2014-01-22 10:57:38
据我所知,在Java7中,它们更改了String类的内部实现,删除了要在不同string之间共享的char[] (偏移量值指示该字符串中的第一个字符和该字符串的长度)。
检查这里,06/
https://stackoverflow.com/questions/21280925
复制相似问题