且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

到一个ArrayList转换为字符串的***方法

更新时间:2023-01-07 23:00:13

基本上,使用循环遍历的ArrayList 是唯一的选择:

Basically, using a loop to iterate over the ArrayList is the only option:

ArrayList<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");

String listString = "";

for (String s : list)
{
    listString += s + "\t";
}

System.out.println(listString);

事实上,一个字符串连接将是蛮好的,因为的javac 编译器将优化字符串连接为一系列的追加的StringBuilder 反正操作。下面是从上述程序的循环字节code的反汇编的一部分:

In fact, a string concatenation is going to be just fine, as the javac compiler will optimize the string concatenation as a series of append operations on a StringBuilder anyway. Here's a part of the disassembly of the bytecode from the for loop from the above program:

   61:  new #13; //class java/lang/StringBuilder
   64:  dup
   65:  invokespecial   #14; //Method java/lang/StringBuilder."<init>":()V
   68:  aload_2
   69:  invokevirtual   #15; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   72:  aload   4
   74:  invokevirtual   #15; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   77:  ldc #16; //String \t
   79:  invokevirtual   #15; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   82:  invokevirtual   #17; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;

可以看出,编译器使用优化的循环中的的StringBuilder ,所以性能不应该是一个大问题。

As can be seen, the compiler optimizes that loop by using a StringBuilder, so performance shouldn't be a big concern.

(OK,在第二眼时,的StringBuilder 在循环的每个迭代被实例化,所以它可能不是最有效的字节code。初始化并使用一个明确的的StringBuilder 可能会产生更好的性能。)

(OK, on second glance, the StringBuilder is being instantiated on each iteration of the loop, so it may not be the most efficient bytecode. Instantiating and using an explicit StringBuilder would probably yield better performance.)

事实上,我认为有任何种类的输出(它是磁盘或屏幕)将至少要比不必担心字符串串联的性能下降一个数量级。

In fact, I think that having any sort of output (be it to disk or to the screen) will be at least an order of a magnitude slower than having to worry about the performance of string concatenations.

编辑:由于在评论中指出,上述编译器优化的确是创建的StringBuilder 在每个迭代一个新的实例。 (我注意到previously。)

As pointed out in the comments, the above compiler optimization is indeed creating a new instance of StringBuilder on each iteration. (Which I have noted previously.)

最优化的技术使用将是Paul汤布林,因为它仅实例化循环外一个的StringBuilder 对象。

The most optimized technique to use will be the response by Paul Tomblin, as it only instantiates a single StringBuilder object outside of the for loop.

重写上述code为:

ArrayList<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");

StringBuilder sb = new StringBuilder();
for (String s : list)
{
    sb.append(s);
    sb.append("\t");
}

System.out.println(sb.toString());

只会实例化的StringBuilder 一旦循环之外,只有使两者调用的追加方法内循环,就证明该字节code(这说明的StringBuilder 的实例化和循环):

Will only instantiate the StringBuilder once outside of the loop, and only make the two calls to the append method inside the loop, as evidenced in this bytecode (which shows the instantiation of StringBuilder and the loop):

   // Instantiation of the StringBuilder outside loop:
   33:  new #8; //class java/lang/StringBuilder
   36:  dup
   37:  invokespecial   #9; //Method java/lang/StringBuilder."<init>":()V
   40:  astore_2

   // [snip a few lines for initializing the loop]
   // Loading the StringBuilder inside the loop, then append:
   66:  aload_2
   67:  aload   4
   69:  invokevirtual   #14; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   72:  pop
   73:  aload_2
   74:  ldc #15; //String \t
   76:  invokevirtual   #14; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   79:  pop

所以,的确是手工优化应该是性能更好,因为循环里面较短,没有必要实例化一个 StringBuilder的在每次迭代。

So, indeed the hand optimization should be better performing, as the inside of the for loop is shorter and there is no need to instantiate a StringBuilder on each iteration.