java中无分配的字符串连接
有没有一种方法可以在不分配内存的情况下连接两个字符串(不是final) 例如,我有两个字符串:java中无分配的字符串连接,java,string,memory,concatenation,allocation,Java,String,Memory,Concatenation,Allocation,有没有一种方法可以在不分配内存的情况下连接两个字符串(不是final) 例如,我有两个字符串: final String SCORE_TEXT = "SCORE: "; String score = "1000"; //or int score = 1000; 当我连接这两个字符串时,将创建一个新的String对象 font.drawMultiLine(batch, SCORE_TEXT + score, 50f, 670f);//this creates new string each ti
final String SCORE_TEXT = "SCORE: ";
String score = "1000"; //or int score = 1000;
当我连接这两个字符串时,将创建一个新的String
对象
font.drawMultiLine(batch, SCORE_TEXT + score, 50f, 670f);//this creates new string each time
由于这是在主游戏循环中完成的(在一秒钟内执行约60次),因此有很多分配
我可以不分配就这样做吗?第一次不理解这个问题。您是否尝试过使用以下方法
SCORE_TEXT.concat(score);
我不认为你可以在没有内存分配的情况下填充一个值。。您最好创建一个全局字符串变量,并向其提供SCORE_TEXT+SCORE的值。在font.drawMultiLine()方法中使用该全局字符串变量 通过这种方式,您可以最大限度地减少分配的内存量,因为内存只分配一次,同一位置会再次更新。
drawMultiLine
不接受字符串,而是接受CharSequence
。因此,您可能会实现自己的CharSequence
,它实际上并不连接两个字符串。以下是实施草案:
public class ConcatenatedString implements CharSequence {
final String left, right;
final int leftLength;
public ConcatenatedString(String left, String right) {
this.left = left;
this.right = right;
this.leftLength = left.length();
}
@Override
public int length() {
return leftLength+right.length();
}
@Override
public char charAt(int index) {
return index < leftLength ? left.charAt(index) : right.charAt(index-leftLength);
}
@Override
public CharSequence subSequence(int start, int end) {
if(end <= leftLength)
return left.substring(start, end);
if(start >= leftLength)
return right.substring(start-leftLength, end-leftLength);
return toString().substring(start, end);
}
@Override
public String toString() {
return left.concat(right);
}
}
在您的案例中,drawMultiline
只需要length
和charAt
方法。使用ConcatenatedString
只创建一个新对象。相反,当您使用SCORE\u TEXT+SCORE
时,您会创建一个临时StringBuilder
,它在内部创建char[]
数组,复制输入符号,根据需要调整数组大小,然后创建最终的String
对象,创建新的char[]
数组并再次复制符号。因此,ConcatenatedString
可能会更快。显而易见的解决方案是不要在每一帧上重新创建输出字符串,而只是在它发生变化时
一种方法是将其存储在主循环之外的某个位置,并在某个事件发生时进行更新,即“分数”实际发生变化。在主循环中,您只需使用预先创建的字符串
如果您不能/或不希望使用这种基于事件的方法,则始终可以存储“先前”分数,并且仅当先前分数与当前分数不同时才连接新字符串
根据你的分数实际变化的频率,这将减少大部分的重新分配。当然,除非分数以60 fps的速度变化,在这种情况下,整个分数是完全静音的,因为没有人能够阅读您正在打印的文本。字符串在Java中是不可变的。使用StringBuilder这是否真的会导致性能问题,或者您正在这样做?是的,由于gc,它实际上会导致性能问题。游戏适用于移动设备,在速度较慢的设备上,gc会导致fps下降…@Kenneth Clark,“字符串格式”会创建一些新对象。例如,格式化程序
,模式
…字符串生成器或缓冲区,直接写入,无需concatsb.toString()代码>创建新字符串使用已实例化的res
对象,而不是在flyscore上关联的对象不是静态字符串,而是动态字符串created@nuno,这与编写String res=SCORE\u TEXT+SCORE
完全相同:javac编译器有效地生成相同的字节码。第一次不理解这个问题-编辑您的建议是不可能的,因为只有在调用toString
或子序列
时,SCORE才是动态字符串。但在您的情况下不太可能。但是,等等,new ConcatenatedString
,这也在创建新对象吗?它只是一个新对象。当您使用SCORE\u TEXT+SCORE
时,您至少创建了四个对象(可能更多)并复制了符号数组。我不知道,我认为它只创建了一个新对象,我想我需要更多地阅读字符串连接…这实际上是目前为止最好的建议。但我认为更好的办法是分别画每根线。我会再打一次平局,但我认为这比很多平局要好得多allocations@pedja您也可以这样做,但是您可能需要手动对齐两个字符串,这在您的情况下可能是可行的,因为第一个字符串是静态的。
font.drawMultiLine(batch, new ConcatenatedString(SCORE_TEXT, score), 50f, 670f);