使用流将对象列表转换为从toString方法获得的字符串

Java 8中有很多有用的新功能。例如,我可以在对象列表上迭代流,然后从Object实例的特定字段中求和。如。

public class AClass {
private int value;
public int getValue() { return value; }
}


Integer sum = list.stream().mapToInt(AClass::getValue).sum();

因此,我问是否有任何方法可以构建一个String,将toString()方法的输出从实例中连接到一行中。

List<Integer> list = ...


String concatenated = list.stream().... //concatenate here with toString() method from java.lang.Integer class

假设list包含整数123,我期望concatenated"123""1,2,3"

492009 次浏览

一个简单的方法是在StringBuilder中添加列表项

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);


StringBuilder b = new StringBuilder();
list.forEach(b::append);


System.out.println(b);

你也可以试试:

String s = list.stream().map(e -> e.toString()).reduce("", String::concat);

解释:map将Integer流转换为String流,然后将其简化为所有元素的连接。

注意:这是normal reduction,在O(n2)中执行

为了获得更好的性能,请使用类似F. Böller的答案的StringBuildermutable reduction

String s = list.stream().map(Object::toString).collect(Collectors.joining(","));

裁判:减少流

API中有一个收集器joining。 它是Collectors中的一个静态方法
list.stream().map(Object::toString).collect(Collectors.joining(","))

由于必须调用toString,所以不完美,但可以工作。可以使用不同的分隔符。

其他答案都没问题。但是,你也可以将Collectors.toList ()作为参数传递给Stream.collect (),以数组列表的形式返回元素。

System.out.println( list.stream().map( e -> e.toString() ).collect( toList() ) );

以防有人试图在没有java 8的情况下做到这一点,这里有一个非常好的技巧。List.toString()已经返回一个类似这样的集合:

(1、2、3)

根据您的具体要求,只要您的列表项不包含[]或,就可以将其后处理为您想要的任何内容。

例如:

list.toString().replace("[","").replace("]","")

或者如果你的数据可能包含方括号:

String s=list.toString();
s = s.substring(1,s.length()-1)

会得到一个相当合理的输出。

每行上可以创建一个数组项,如下所示:

list.toString().replace("[","").replace("]","").replaceAll(",","\r\n")

我使用这种技术从一个小应用程序的列表中制作html工具提示,如下所示:

list.toString().replace("[","<html>").replace("]","</html>").replaceAll(",","<br>")

如果你有一个数组,那么从Arrays.asList(list).toString()开始

我完全承认这不是最优的事实,但它并不像您想象的那么低效,而且很容易阅读和理解。然而,它是相当不灵活的——特别是不要尝试用replaceAll来分隔元素,如果您的数据中可能包含逗号,如果您的数据中有方括号,则使用子字符串版本,但对于数字数组来说,它几乎是完美的。

我们可以试试这个吗?

public static void main(String []args){
List<String> stringList = new ArrayList<>();
for(int i=0;i< 10;i++){
stringList.add(""+i);
}
String stringConcated = String.join(",", stringList);
System.out.println(stringConcated);


}
String actual = list.stream().reduce((t, u) -> t + "," + u).get();

你也可以这样做。

    List<String> list = Arrays.asList("One", "Two", "Three");
String result = String.join(", ", list);
System.out.println(result);

Java 8+

String s = Arrays.toString(list.stream().toArray(AClass[]::new));

虽然不是最有效的,但它是一种只需少量代码的解决方案。

List<String> list = Arrays.asList("One", "Two", "Three");
list.stream()
.reduce("", org.apache.commons.lang3.StringUtils::join);

List<String> list = Arrays.asList("One", "Two", "Three");
list.stream()
.reduce("", (s1,s2)->s1+s2);
此方法还允许您从对象列表构建字符串结果 示例< / p >
List<Wrapper> list = Arrays.asList(w1, w2, w2);
list.stream()
.map(w->w.getStringValue)
.reduce("", org.apache.commons.lang3.StringUtils::join);
这里的reduce函数允许你有一些初始值,你想追加一个新的字符串 例子:< / p >
 List<String> errors = Arrays.asList("er1", "er2", "er3");
list.stream()
.reduce("Found next errors:", (s1,s2)->s1+s2);

测试Shail016bpedroso答案(https://stackoverflow.com/a/24883180/2832140)中建议的两种方法,即for循环中的简单StringBuilder + append(String),似乎比list.stream().map([...]执行得快得多。

示例:下面的代码遍历一个Map<Long, List<Long>>,使用list.stream().map([...]构建一个json字符串:

if (mapSize > 0) {
StringBuilder sb = new StringBuilder("[");


for (Map.Entry<Long, List<Long>> entry : threadsMap.entrySet()) {


sb.append("{\"" + entry.getKey().toString() + "\":[");
sb.append(entry.getValue().stream().map(Object::toString).collect(Collectors.joining(",")));
}
sb.delete(sb.length()-2, sb.length());
sb.append("]");
System.out.println(sb.toString());
}

在我的dev VM上,junit通常需要0.35到1.2秒来执行测试。然而,使用下面的代码,它需要0.15到0.33秒:

if (mapSize > 0) {
StringBuilder sb = new StringBuilder("[");


for (Map.Entry<Long, List<Long>> entry : threadsMap.entrySet()) {


sb.append("{\"" + entry.getKey().toString() + "\":[");


for (Long tid : entry.getValue()) {
sb.append(tid.toString() + ", ");
}
sb.delete(sb.length()-2, sb.length());
sb.append("]}, ");
}
sb.delete(sb.length()-2, sb.length());
sb.append("]");
System.out.println(sb.toString());
}

StringListName = ObjectListName.stream()。map(m -> m. tostring())。collect(collections . tolist ());

在String API中有一个方法用于那些“连接字符串列表”的用例,你甚至不需要Stream。

List<String> myStringIterable = Arrays.asList("baguette", "bonjour");


String myReducedString = String.join(",", myStringIterable);


// And here you obtain "baguette,bonjour" in your myReducedString variable

我将使用streams api将整数流转换为单个字符串。提供的一些答案的问题是,由于构建String,它们产生了O(n²)运行时。更好的解决方案是使用StringBuilder,然后在最后一步将字符串连接在一起。

//              Create a stream of integers
String result = Arrays.stream(new int[]{1,2,3,4,5,6 })
// collect into a single StringBuilder
.collect(StringBuilder::new, // supplier function
// accumulator - converts cur integer into a string and appends it to the string builder
(builder, cur) -> builder.append(Integer.toString(cur)),
// combiner - combines two string builders if running in parallel
StringBuilder::append)
// convert StringBuilder into a single string
.toString();

您可以通过将object的集合转换为单个字符串来进一步执行此过程。

// Start with a class definition
public static class AClass {
private int value;
public int getValue() { return value; }
public AClass(int value) { this.value = value; }


@Override
public String toString() {
return Integer.toString(value);
}
}


// Create a stream of AClass objects
String resultTwo = Arrays.stream(new AClass[]{
new AClass(1),
new AClass(2),
new AClass(3),
new AClass(4)
})
// transform stream of objects into a single string
.collect(StringBuilder::new,
(builder, curObj) -> builder.append(curObj.toString()),
StringBuilder::append
)
// finally transform string builder into a single string
.toString();

一种简洁的方法是将列表中的元素映射为字符串,然后在Collectors类中使用joining操作。

List<Integer> ls = new ArrayList<Integer>();
ls.add(1);
ls.add(2);
ls.add(3);
String s = ls.stream().map(Object::toString).collect(Collectors.joining(","));