简体   繁体   English

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

[英]Using streams to convert a list of objects into a string obtained from the toString method

There are a lot of useful new things in Java 8. Eg, I can iterate with a stream over a list of objects and then sum the values from a specific field of the Object 's instances. Java 8 中有很多有用的新内容。例如,我可以使用 stream 对对象列表进行迭代,然后将来自Object实例的特定字段的值相加。 Eg例如

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

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

Thus, I'm asking if there is any way to build a String that concatenates the output of the toString() method from the instances in a single line.因此,我问是否有任何方法可以构建一个String ,该字符串将来自实例的toString()方法的 output 连接在一行中。

List<Integer> list = ...

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

Suppose that list contains integers 1 , 2 and 3 , I expect that concatenated is "123" or "1,2,3" .假设list包含整数123 ,我希望concatenated的是"123""1,2,3"

One simple way is to append your list items in a StringBuilder一种简单的方法是将列表项附加到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);

you can also try:你也可以尝试:

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

Explanation: map converts Integer stream to String stream, then its reduced as concatenation of all the elements.说明:map 将 Integer 流转换为 String 流,然后将其缩减为所有元素的串联。

Note: This is normal reduction which performs in O(n 2 )注意:这是在 O(n 2 ) 中执行的normal reduction

for better performance use a StringBuilder or mutable reduction similar to F. Böller's answer.为了获得更好的性能,请使用类似于 F. Böller 的答案的StringBuildermutable reduction

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

Ref: Stream Reduction参考: 流减少

There is a collector joining in the API.有一个收集器joining API。 It's a static method in Collectors .这是Collectors的静态方法。

list.stream().map(Object::toString).collect(Collectors.joining(","))

Not perfect because of the necessary call of toString , but works.由于toString的必要调用,并不完美,但有效。 Different delimiters are possible.不同的分隔符是可能的。

Just in case anyone is trying to do this without java 8, there is a pretty good trick.以防万一有人试图在没有 Java 8 的情况下执行此操作,这里有一个很好的技巧。 List.toString() already returns a collection that looks like this: List.toString() 已经返回一个如下所示的集合:

[1,2,3] [1,2,3]

Depending on your specific requirements, this can be post-processed to whatever you want as long as your list items don't contain [] or , .根据您的具体要求,只要您的列表项不包含 [] 或 , ,就可以将其后处理为您想要的任何内容。

For instance:例如:

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

or if your data might contain square brackets this:或者如果您的数据可能包含方括号:

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

will get you a pretty reasonable output.会给你一个相当合理的输出。

One array item on each line can be created like this:可以像这样在每一行上创建一个数组项:

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

I used this technique to make html tooltips from a list in a small app, with something like:我使用这种技术从一个小应用程序的列表中制作 html 工具提示,例如:

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

If you have an array then start with Arrays.asList(list).toString() instead如果你有一个数组,那么从 Arrays.asList(list).toString() 开始

I'll totally own the fact that this is not optimal, but it's not as inefficient as you might think and is pretty straightforward to read and understand.我完全承认这不是最优的,但它并不像您想象的那么低效,并且非常易于阅读和理解。 It is, however, quite inflexible--in particular don't try to separate the elements with replaceAll if your data might contain commas and use the substring version if you have square brackets in your data, but for an array of numbers it's pretty much perfect.但是,它非常不灵活 - 特别是如果您的数据可能包含逗号,请不要尝试使用 replaceAll 分隔元素,如果您的数据中有方括号,请使用子字符串版本,但对于数字数组,它几乎是完美的。

There is a method in the String API for those "joining list of string" usecases, you don't even need Stream.对于那些“连接字符串列表”用例,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

The other answers are fine.其他答案都很好。 However, you can also pass Collectors.toList() as parameter to Stream.collect() to return the elements as an ArrayList.但是,您也可以将Collectors.toList()作为参数传递给Stream.collect()以将元素作为 ArrayList 返回。

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

StringListName = ObjectListName.stream().map( m -> m.toString() ).collect( Collectors.toList() );

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

Or或者

List<String> list = Arrays.asList("One", "Two", "Three");
        list.stream()
                .reduce("", (s1,s2)->s1+s2);

This approach allows you also build a string result from a list of objects Example这种方法还允许您从对象列表中构建字符串结果示例

List<Wrapper> list = Arrays.asList(w1, w2, w2);
        list.stream()
                .map(w->w.getStringValue)
                .reduce("", org.apache.commons.lang3.StringUtils::join);

Here the reduce function allows you to have some initial value to which you want to append new string Example:在这里,reduce 函数允许您拥有一些要附加新字符串的初始值示例:

 List<String> errors = Arrays.asList("er1", "er2", "er3");
            list.stream()
                    .reduce("Found next errors:", (s1,s2)->s1+s2);

Testing both approaches suggested in Shail016 and bpedroso answer ( https://stackoverflow.com/a/24883180/2832140 ), the simple StringBuilder + append(String) within a for loop, seems to execute much faster than list.stream().map([...] .测试Shail016bpedroso答案( https://stackoverflow.com/a/24883180/2832140 )中建议的两种方法, for循环中的简单StringBuilder + append(String)似乎比list.stream().map([...]执行得快得多list.stream().map([...] .

Example: This code walks through a Map<Long, List<Long>> builds a json string, using list.stream().map([...] :示例:此代码遍历Map<Long, List<Long>>构建一个 json 字符串,使用list.stream().map([...]

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());
}

On my dev VM, junit usually takes between 0.35 and 1.2 seconds to execute the test.在我的开发 VM 上,junit 通常需要 0.35 到 1.2 秒来执行测试。 While, using this following code, it takes between 0.15 and 0.33 seconds:而使用以下代码,它需要 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());
}

Can we try this.我们可以试试这个。

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();

I'm going to use the streams api to convert a stream of integers into a single string.我将使用流 api 将整数流转换为单个字符串。 The problem with some of the provided answers is that they produce a O(n^2) runtime because of String building.一些提供的答案的问题在于,由于字符串构建,它们会产生 O(n^2) 运行时。 A better solution is to use a StringBuilder, and then join the strings together as the final step.更好的解决方案是使用 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();

You can take this process a step further by converting the collection of object to a single string.您可以通过将对象集合转换为单个字符串来进一步执行此过程。

// 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();

A clean way to do this is by mapping the elements of the list to string and then using the joining operation in Collectors class.一个干净的方法是将列表的元素映射到字符串,然后使用Collectors class 中的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(","));

With Java 8+使用 Java 8+

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

Not the most efficient, but it is a solution with a small amount of code.不是最有效的,但它是一个代码量很少的解决方案。

Also, you can do like this.另外,你可以这样做。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM