字符串连接,在java中没有分配

时间:2015-05-28 09:43:00

标签: java string memory concatenation allocation

有没有办法在不分配内存的情况下连接两个字符串(而不是最终字符串)?

例如,我有这两个字符串:

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次),因此有很多分配。

我可以不分配地以某种方式做到这一点吗?

5 个答案:

答案 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只需要lengthcharAt方法。使用ConcatenatedString只能创建一个新对象。相反,当您使用SCORE_TEXT + score时,您创建一个临时StringBuilder,它会创建内部char[]数组,复制输入符号,必要时调整数组大小,然后创建最终String创建新char[]数组并再次复制符号的对象。因此,ConcatenatedString可能会更快。

答案 3 :(得分:0)

我不认为你可以在不为其分配内存的情况下填充值。你能做的最好的事情是创建一个全局字符串变量并为其提供SCORE_TEXT +得分的值。在font.drawMultiLine()方法中使用该全局字符串变量。

这样,您可以最小化分配的内存量,因为内存只分配一次,同一位置再次更新&amp;试。

答案 4 :(得分:0)

String设计为在Java中不可变。使用StringBuilder