使用Java 8将对象列表转换为从toString()方法获取的字符串

mat*_*boy 177 java-8 java-stream

Java 8中有许多有用的新东西.例如,我可以在一个对象列表上迭代一个流,然后对来自Object实例的特定字段的值求和.例如

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

Integer sum = list.stream().mapToInt(AClass::getValue).sum();
Run Code Online (Sandbox Code Playgroud)

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

List<Integer> list = ...

String concatenated = list.stream().... //concatenate here with toString() method from java.lang.Integer class
Run Code Online (Sandbox Code Playgroud)

假设list包含整数1,2并且3我希望它concatenated"123""1,2,3".

Sha*_*016 326

一种简单的方法是将您的列表项追加到 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);
Run Code Online (Sandbox Code Playgroud)

你也可以尝试:

String s = list.stream().map(e -> e.toString()).reduce("", String::concat);
Run Code Online (Sandbox Code Playgroud)

说明:map将Integer流转换为String流,然后将其缩减为所有元素的串联.

注意:这是normal reduction在O(n 2)中执行的

为了更好的表现,使用StringBuildermutable reduction类似于F.Böller的答案.

String s = list.stream().map(Object::toString).collect(Collectors.joining(","));
Run Code Online (Sandbox Code Playgroud)

参考:流减少

  • 是的,不是内联解决方案,而是解决方案。 (2认同)
  • 我不明白为什么"在O(n2)中执行的正常减少".对我而言,"看起来"更像是O(n)...... (2认同)
  • @datahaki我不是Java人,但我猜测迭代字符串连接(缩减)需要在每次迭代时进行数组(重新)分配,这使得它成为O(n ^ 2).另一边的`join`会预先分配一个足够大的单个数组,以便在填充它之前存储最终字符串,使其成为O(n). (2认同)
  • 很好的小费。也许您可以使用“ ::”符号来简化。因此,`list.stream()。map(Object :: toString).reduce(“”,String :: concat)`。使用`map e-&gt; e.toString()`有点多余。 (2认同)

F. *_*ler 179

joiningAPI中有一个收集器.这是一个静态的方法Collectors.

list.stream().map(Object::toString).collect(Collectors.joining(","))
Run Code Online (Sandbox Code Playgroud)

因为必要的召唤而不完美toString,但是有效.不同的分隔符是可能的.

  • 为了完整性:要获得确切的代码,你需要`import static java.util.stream.Collectors.joining;` (6认同)
  • 为什么我们需要映射和显式的`toString'?如果收集器期望String元素,那么应该隐式调用转换,不是吗?! (6认同)

Bil*_*l K 10

为了防止有人在没有java 8的情况下尝试这样做,有一个非常好的技巧.List.toString()已经返回一个如下所示的集合:

[1,2,3]

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

例如:

list.toString().replace("[","").replace("]","") 
Run Code Online (Sandbox Code Playgroud)

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

String s=list.toString();
s = s.substring(1,s.length()-1) 
Run Code Online (Sandbox Code Playgroud)

会给你一个非常合理的输出.

可以像这样创建每行上的一个数组项:

list.toString().replace("[","").replace("]","").replaceAll(",","\r\n")
Run Code Online (Sandbox Code Playgroud)

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

list.toString().replace("[","<html>").replace("]","</html>").replaceAll(",","<br>")
Run Code Online (Sandbox Code Playgroud)

如果你有一个数组,那么请先使用Arrays.asList(list).toString()

我完全拥有这样一个事实,即这不是最优的,但它并不像你想象的那样低效,并且阅读和理解非常简单.但是,它非常不灵活 - 特别是如果您的数据可能包含逗号而不尝试使用replaceAll分隔元素,并且如果数据中有方括号,则使用子字符串版本,但对于数组数组,它​​几乎是完善.


Bac*_*hrc 7

对于那些“连接字符串列表”用例,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
Run Code Online (Sandbox Code Playgroud)


Edd*_*e B 5

其他答案很好。但是,您也可以将Collectors.toList()作为参数传递给Stream.collect(),以将元素作为ArrayList返回。

System.out.println( list.stream().map( e -> e.toString() ).collect( toList() ) );
Run Code Online (Sandbox Code Playgroud)