我已编写此代码以连接ArrayList元素: 它可以更优化吗?或者有更好的不同方式吗?
public static String join(ArrayList list, char delim) {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < list.size(); i++) {
if (i != 0)
buf.append(delim);
buf.append((String) list.get(i));
}
return buf.toString();
}
答案 0 :(得分:2)
StringBuffer是为了线程安全而同步的,而是使用StringBuilder。
不要在循环的每次迭代中调用list.size()。将其设置为变量或使用迭代器。
另请注意,有很多库可以执行此操作,主要是google collections。请尝试以下方法:
public String join(List<?> list, char delimiter) {
StringBuilder result = new StringBuilder();
for (Iterator<?> i = list.iterator(); i.hasNext();) {
result.append(i.next());
if (i.hasNext()) {
result.append(delimiter);
}
}
return result.toString();
}
答案 1 :(得分:2)
为什么你需要一种方法?为什么不直接使用toString()方法?
public static String join(List<String> list)
{
return list.toString(); // comma delimiter with some extra stuff at start and end
}
你可以比你写的方法做得更好。添加List接口和泛型;也许甚至收藏。它更通用,更安全;不需要演员表。
运行此类:
import java.util.Arrays;
import java.util.List;
public class ListToStringDemo
{
public static void main(String[] args)
{
List<String> values = Arrays.asList(args);
System.out.println(values);
}
}
在命令行中使用任何字符串参数(例如,“foo bar baz bat”)并获得此输出:
C:\JDKs\jdk1.6.0_13\bin\java ListToStringDemo foo bar baz bat
[foo, bar, baz, bat]
Process finished with exit code 0
答案 2 :(得分:2)
Here是着名的java.util.Collection团队正在做的事情,所以我认为这应该是相当不错的;)
421 /* Returns a string representation of this collection. The string
422 * representation consists of a list of the collection's elements in the
423 * order they are returned by its iterator, enclosed in square brackets
424 * (<tt>"[]"</tt>). Adjacent elements are separated by the characters
425 * <tt>", "</tt> (comma and space). Elements are converted to strings as
426 * by {@link String#valueOf(Object)}.
427 *
428 * @return a string representation of this collection
429 */
430 public String toString() {
431 Iterator<E> i = iterator();
432 if (! i.hasNext())
433 return "[]";
434
435 StringBuilder sb = new StringBuilder();
436 sb.append('[');
437 for (;;) {
438 E e = i.next();
439 sb.append(e == this ? "(this Collection)" : e);
440 if (! i.hasNext())
441 return sb.append(']').toString();
442 sb.append(", ");
443 }
另外,这就是你如何用duffymo的答案得到逗号分隔符;)
答案 3 :(得分:1)
这是否已知肯定会导致某些性能问题,或者您是否正在将此作为练习?如果没有,我不会打扰。
我假设这可能会更快,但我对此表示怀疑:
StringBuffer buf = new StringBuffer();
for (int i = 0; i < list.size() - 1; i++) {
buf.append((String) list.get(i));
buf.append(delim);
}
buf.append((String) list.get(i));
return buf.toString();
答案 4 :(得分:1)
我的第一个想法是,Google Collection的Joiner课程将是一个有用的起点。具体来说,是public final String join(Iterable<?> parts)
方法。
答案 5 :(得分:1)
每次循环迭代时,你都在检查列表的大小:
for (int i = 0; i < list.size(); i++) {
由于您没有改变列表,您只需要执行一次:
for (int i = 0, j = list.size(); i < j; i++) {
不是在每次迭代中检查i != 0
,而是在每次迭代后附加一个分隔符:
for (int i = 0; i < list.size(); i++) {
buf.append((String) list.get(i));
buf.append(delim);
}
// Here, convert all but the last character in the buffer to a string.
答案 6 :(得分:0)
更好,也许:
列出而不是ArrayList
接口程序而非实现
根据Josh,来自1.5的foreach循环实际上更有效率,并且更容易理解 其他人已经注意到for(String string:strings)而不是for(int i ...)
等
答案 7 :(得分:0)
我怀疑它可能会显着优化(意味着变得更快)而不会变得神秘。但是,使用泛型可以改进。
public static String join(List<String> list, char delim) {
StringBuffer buf = new StringBuffer(512);
first = true;
for (String item : list) {
if (first) {
first = false;
} else {
buf.append(delim);
}
buf.append(item);
}
}
此版本的改进:您强制要求项目仅包含编译器级别的字符串,您不必维护循环变量,并且您不需要ArrayList,这是API的实现细节不应强制执行。
答案 8 :(得分:0)
除了您收到的答案外,您还可以预先初始化StringBuilder
或StringBuffer
的容量。这减少了内部数组在扩展时必须重新复制的次数。由于您不知道所需的确切容量,因此您可以根据元素数量估算每个元素的平均大小和倍数。
private static final int ESTIMATE_ELEM_SIZE = 8;
public static String join(Collection col, char delim)
{
int len = col.size();
if (len == 0)
return "";
StringBuilder buf = new StringBuilder(ESTIMATE_ELEM_SIZE * len);
for (Object elem : col)
{
buf.append(elem).append(delim);
}
return buf.substring(0, buf.length() - 1);
}
这显示了其他人分享的一些技巧:使用StringBuilder
,不要在循环中检查if
,并使用foreach增强循环。
我还建议将第一个参数更改为有意义的最通用类型,以便它更具可重用性。在这种情况下,由于您确实不需要索引来处理每个元素,因此可以指定Collection
。
请注意,也不需要转发String
,因为StringBuilder.append()
会在必要时将元素转换为String
。这允许您将其用于包含除字符串以外的其他类型对象的集合。