有没有办法在不分配内存的情况下连接两个字符串(而不是最终字符串)?
例如,我有这两个字符串:
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次),因此有很多分配。
我可以不分配地以某种方式做到这一点吗?
答案 0 :(得分:4)
显而易见的解决方案是不在每个帧上重新创建输出String
,而只是在它发生变化时。
执行此操作的一种方法是将其存储在主循环之外的某个位置,并在某个事件发生时更新它,即"得分"实际上是变化在主循环中,您只需使用预先创建的String
。
如果您不能/或者不希望采用这种基于事件的方法,您可以随时存储"之前的"得分并且只有当前一个得分与当前得分不同时才连接新的字符串。
根据您的分数实际更改的频率,这应该会删除大多数重新分配。除非分数以60 fps的速度变化,在这种情况下,这一点完全是静音的,因为没有人能够阅读您正在打印的文本。
答案 1 :(得分:1)
第一次没有理解这个问题。您是否尝试过使用以下内容?
var width = 400,
height = 430
num_axes = 8,
tick_axis = 1,
start = 0
end = 4;
var theta = function(r) {
return -2*Math.PI*r;
};
var arc = d3.svg.arc()
.startAngle(0)
.endAngle(2*Math.PI);
var radius = d3.scale.linear()
.domain([start, end])
.range([0, d3.min([width,height])/2-20]);
var angle = d3.scale.linear()
.domain([0,num_axes])
.range([0,360])
var svg = d3.select("#chart").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width/2 + "," + (height/2+8) +")");
var pieces = d3.range(start, end+0.001, (end-start)/1000);
var spiral = d3.svg.line.radial()
.interpolate("cardinal")
.angle(theta)
.radius(radius);
//svg.append("text")
// .text("And there was much rejoicing!")
// .attr("class", "title")
// .attr("x", 0)
// .attr("y", -height/2+16)
// .attr("text-anchor", "middle")
//svg.selectAll("circle.tick")
// .data(d3.range(end,start,(start-end)/4))
// .enter().append("circle")
// .attr("class", "tick")
// .attr("cx", 0)
// .attr("cy", 0)
// .attr("r", function(d) { return radius(d); })
svg.selectAll(".axis")
.data(d3.range(num_axes))
.enter().append("g")
.attr("class", "axis")
.attr("transform", function(d) { return "rotate(" + -angle(d) + ")"; })
.call(radial_tick)
.append("text")
.attr("y", radius(end)+13)
.text(function(d) { return angle(d) + "°"; })
.attr("text-anchor", "middle")
.attr("transform", function(d) { return "rotate(" + -90 + ")" })
svg.selectAll(".spiral")
.data([pieces])
.enter().append("path")
.attr("class", "spiral")
.attr("d", spiral)
.attr("transform", function(d) { return "rotate(" + 90 + ")" });
function radial_tick(selection) {
selection.each(function(axis_num) {
d3.svg.axis()
.scale(radius)
.ticks(5)
.tickValues( axis_num == tick_axis ? null : [])
.orient("bottom")(d3.select(this))
d3.select(this)
.selectAll("text")
.attr("text-anchor", "bottom")
.attr("transform", "rotate(" + angle(axis_num) + ")")
});
}
答案 2 :(得分:1)
Seems that drawMultiLine
不接受String
,而是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);
}
}
像这样使用:
font.drawMultiLine(batch, new ConcatenatedString(SCORE_TEXT, score), 50f, 670f);
在您的案例内drawMultiline
只需要length
和charAt
方法。使用ConcatenatedString
只能创建一个新对象。相反,当您使用SCORE_TEXT + score
时,您创建一个临时StringBuilder
,它会创建内部char[]
数组,复制输入符号,必要时调整数组大小,然后创建最终String
创建新char[]
数组并再次复制符号的对象。因此,ConcatenatedString
可能会更快。
答案 3 :(得分:0)
我不认为你可以在不为其分配内存的情况下填充值。你能做的最好的事情是创建一个全局字符串变量并为其提供SCORE_TEXT +得分的值。在font.drawMultiLine()方法中使用该全局字符串变量。
这样,您可以最小化分配的内存量,因为内存只分配一次,同一位置再次更新&amp;试。
答案 4 :(得分:0)
String设计为在Java中不可变。使用StringBuilder