我有一个ArrayList
我想完全输出为String的。本质上,我想使用toString
由制表符分隔的每个元素按顺序输出。有什么快速的方法可以做到这一点吗?您可以遍历它(或删除每个元素)并将其连接为字符串,但是我认为这会非常慢。
我有一个ArrayList
我想完全输出为String的。本质上,我想使用toString
由制表符分隔的每个元素按顺序输出。有什么快速的方法可以做到这一点吗?您可以遍历它(或删除每个元素)并将其连接为字符串,但是我认为这会非常慢。
Answers:
基本上,使用循环来迭代ArrayList
是唯一的选择:
不要使用此代码,请继续阅读此答案的底部,以了解为什么不希望使用此代码,以及应该使用哪个代码代替:
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
编译器无论如何都会通过一系列append
操作来优化字符串串联StringBuilder
。这是for
上面程序从循环中反汇编字节码的一部分:
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
,因此性能不是大问题。
(好的,乍一看,StringBuilder
在每次循环迭代时都会实例化,因此它可能不是最有效的字节码。实例化和使用显式StringBuilder
可能会产生更好的性能。)
实际上,我认为拥有任何类型的输出(无论是输出到磁盘还是输出到屏幕)至少要比担心字符串连接的性能慢一个数量级。
编辑:正如评论中指出的那样,上面的编译器优化确实是StringBuilder
在每次迭代中创建的新实例。(我之前已经提到过。)
使用最优化的技术是Paul Tomblin的响应,因为它仅实例化循环StringBuilder
外的单个对象for
。
将上面的代码重写为:
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
循环外的一次,并且仅对append
循环内的方法进行两次调用,如以下字节码所示(显示和的实例化StringBuilder
):
// 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
因此,实际上,手优化应该表现得更好,因为for
循环内部更短,并且不需要StringBuilder
在每次迭代时实例化a 。
Java
或Geewax的相关信息Android
在Java 8或更高版本中:
String listString = String.join(", ", list);
如果list
不是String类型,则可以使用联接收集器:
String listString = list.stream().map(Object::toString)
.collect(Collectors.joining(", "));
如果您恰巧在Android上执行此操作,则有一个名为TextUtils的不错的实用程序,它具有一个.join(String delimiter, Iterable)
方法。
List<String> list = new ArrayList<String>();
list.add("Item 1");
list.add("Item 2");
String joined = TextUtils.join(", ", list);
显然,在Android之外没有太多使用,但是我想将其添加到此线程中...
TextUtils.join
采用Object[]
,我假设它正在调用toString()
每个令牌。是否PatientDetails
实现toString()
?如果那不能解决问题,则您可能无法在Separator
该类上做一些事情。
org.apache.lang3.StringUtils
几乎一样,所以您的答案对Android以外的人来说绝对有用:)
下载Apache Commons Lang并使用该方法
StringUtils.join(list)
StringUtils.join(list, ", ") // 2nd param is the separator.
当然,您可以自己实现它,但是它们的代码已经过全面测试,可能是最好的实现。
我是Apache Commons库的忠实拥护者,我也认为它是Java Standard Library的重要补充。
StringUtils.join(list.toArray(),"\t")
将列表更改为可读且有意义的字符串确实是每个人都可能遇到的常见问题。
案例1。如果您的类路径中有apache的StringUtils(例如来自rogerdpack和Ravi Wallau):
import org.apache.commons.lang3.StringUtils;
String str = StringUtils.join(myList);
情况2。如果只想使用JDK(7)中的方法:
import java.util.Arrays;
String str = Arrays.toString(myList.toArray());
只是不要自己动手制作轮子,不要在此单线任务中使用循环。
Arrays.toString(myList.toArray())
-最简单,最直接的解决方案
Arrays.toString(list.toArray())
易于编写,但效率极低。
如果您正在寻找一种快速的单行代码,那么从Java 5开始,您可以执行以下操作:
myList.toString().replaceAll("\\[|\\]", "").replaceAll(", ","\t")
另外,如果您的目的只是打印内容,而不关心“ \ t”,则可以执行以下操作:
myList.toString()
它返回一个类似的字符串
[str1,str2,str3]
如果您有一个Array(而不是ArrayList),则可以完成以下操作:
Arrays.toString(myList).replaceAll("\\[|\\]", "").replaceAll(", ","\t")
m
家庭中寻找人,您会说是或,但是我可以改写“在这个国家寻找这个人”,然后您会立即告诉我。最重要的是,这里所有算法通常都是,循环内没有循环。n
x
O(mnx)
O(n^3)
O(n)
O(n)
遍历它并调用toString。没有一种神奇的方法,如果有的话,除了循环浏览之外,您认为它会在幕后做什么?关于唯一的微优化,是使用StringBuilder而不是String,即使那也不是一个大赢家-将字符串串联起来就变成了StringBuilder的内幕,但至少如果您以这种方式编写,您可以看到发生了什么。
StringBuilder out = new StringBuilder();
for (Object o : list)
{
out.append(o.toString());
out.append("\t");
}
return out.toString();
大多数Java项目通常都提供apache-commons lang。StringUtils.join()方法非常好,并且具有多种功能可以满足几乎所有需求。
public static java.lang.String join(java.util.Collection collection,
char separator)
public static String join(Iterator iterator, String separator) {
// handle null, zero and one elements before building a buffer
Object first = iterator.next();
if (!iterator.hasNext()) {
return ObjectUtils.toString(first);
}
// two or more elements
StringBuffer buf =
new StringBuffer(256); // Java default is 16, probably too small
if (first != null) {
buf.append(first);
}
while (iterator.hasNext()) {
if (separator != null) {
buf.append(separator);
}
Object obj = iterator.next();
if (obj != null) {
buf.append(obj);
}
}
return buf.toString();
}
参数:
collection-要连接在一起的值的Collection,可以为null
分隔符 -要使用的分隔符
返回:联接的String,如果null迭代器输入,则返回 null
从:2.3
join(...)
方法具有数组和集合的变体。
Android具有TextUtil类,您可以使用http://developer.android.com/reference/android/text/TextUtils.html
String implode = TextUtils.join("\t", list);
处理尾随分隔符的一种优雅方法是使用Class Separator
StringBuilder buf = new StringBuilder();
Separator sep = new Separator("\t");
for (String each: list) buf.append(sep).append(each);
String s = buf.toString();
类分隔符的toString方法返回分隔符,除了第一个调用。因此,我们在打印列表时不使用尾部(或在此情况下)前导分隔符。
在Java 8中很简单。请参阅示例以获取整数列表:
String result = Arrays.asList(1,2,3).stream().map(Object::toString).reduce((t, u) -> t + "\t" + u).orElse("");
或多行版本(更易于阅读):
String result = Arrays.asList(1,2,3).stream()
.map(Object::toString)
.reduce((t, u) -> t + "\t" + u)
.orElse("");
String result = Arrays.asList(1,2,3).stream()
.map(Object::toString)
.collect(Collectors.joining("\t"));
filter
。最后,对我来说,阅读代码要容易得多。
String
,最后一条注释才有效。如果它的列表Integer
有问题
如果您碰巧是在Android上并且尚未使用Jack(例如,因为它仍不支持Instant Run),并且您想对生成的字符串的格式进行更多控制(例如,您希望将换行符用作,并且恰好使用/想要使用StreamSupport库(用于在Java 7或更早版本的编译器上使用流),您可以使用类似的方法(我将此方法放在ListUtils类中):
public static <T> String asString(List<T> list) {
return StreamSupport.stream(list)
.map(Object::toString)
.collect(Collectors.joining("\n"));
}
当然,请确保在列表对象的类上实现toString()。
reduce
对于String串联,使用效率极低。您应该return StreamSupport.stream(list).map(Object::toString).collect(joining("\n"))
使用内部使用的Java 8方法StringJoiner
。没有理由您也无法使用streamsupport做到这一点。
Optional#get
传递了一个空列表,则该代码将严重失败(由于)。
如果您不希望最后一个\ t出现在最后一个元素之后,则必须使用索引进行检查,但是请记住,当列表实现RandomAccess时,这只能“起作用”(即O(n))。
List<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
StringBuilder sb = new StringBuilder(list.size() * apprAvg); // every apprAvg > 1 is better than none
for (int i = 0; i < list.size(); i++) {
sb.append(list.get(i));
if (i < list.size() - 1) {
sb.append("\t");
}
}
System.out.println(sb.toString());
可能不是最好的方法,而是优雅的方法。
Arrays.deepToString(Arrays.asList(“ Test”,“ Test2”)
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
System.out.println(Arrays.deepToString(Arrays.asList("Test", "Test2").toArray()));
}
}
输出量
[测试,测试2]
如果您使用的是Eclipse Collections,则可以使用该makeString()
方法。
ArrayList<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
Assert.assertEquals(
"one\ttwo\tthree",
ArrayListAdapter.adapt(list).makeString("\t"));
如果可以将转换ArrayList
为FastList
,则可以摆脱适配器。
Assert.assertEquals(
"one\ttwo\tthree",
FastList.newListWith("one", "two", "three").makeString("\t"));
注意:我是Eclipse Collections的提交者。
一行:从[12,0,1,78,12]到12 0 1 78 12
String srt= list.toString().replaceAll("\\[|\\]|,","");
我看到了很多依赖于其他资源的示例,但这似乎是最简单的解决方案:(这是我在自己的项目中使用的方法),它基本上只是从ArrayList转换为Array,然后转换为List 。
List<Account> accounts = new ArrayList<>();
public String accountList()
{
Account[] listingArray = accounts.toArray(new Account[accounts.size()]);
String listingString = Arrays.toString(listingArray);
return listingString;
}
到目前为止,这是一个相当古老的话题,并且apache commons现在正在内部使用StringBuilder:http : //commons.apache.org/lang/api/src-html/org/apache/commons/lang/StringUtils.html#line。 3045
据我们所知,这将提高性能,但是如果性能至关重要,则所使用的方法可能会有些效率低下。尽管该接口是灵活的,并且将允许在不同Collection类型之间保持一致的行为,但对于Lists而言,效率是低下的,而Lists是原始问题中的Collection类型。
我这样做的基础是,我们会产生一些开销,通过简单地循环访问传统的for循环中的元素可以避免这些开销。相反,在后台检查并发修改,方法调用等情况时会发生其他事情。另一方面,由于在Iterable对象(列表)上使用了迭代器,因此增强的for循环将导致相同的开销。
您可以为此使用正则表达式。简明扼要
System.out.println(yourArrayList.toString().replaceAll("\\[|\\]|[,][ ]","\t"));
这个功能如何:
public static String toString(final Collection<?> collection) {
final StringBuilder sb = new StringBuilder("{");
boolean isFirst = true;
for (final Object object : collection) {
if (!isFirst)
sb.append(',');
else
isFirst = false;
sb.append(object);
}
sb.append('}');
return sb.toString();
}
它适用于任何类型的收藏...