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

时间:2014-07-22 08:54:38

标签: java-8 java-stream

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

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"

13 个答案:

答案 0 :(得分:293)

一种简单的方法是将您的列表项追加到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(n 2 )中执行

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

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

参考:Stream Reduction

答案 1 :(得分:155)

API中有一个收集器joining。 它是Collectors中的静态方法。

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

由于toString的必要调用而不完美,但有效。可能有不同的分隔符。

答案 2 :(得分:10)

万一有人在没有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分隔元素,如果数据中有方括号,则使用子字符串版本,但对于数组数组,则使用#39;非常完美。

答案 3 :(得分:4)

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

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

答案 4 :(得分:4)

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

答案 5 :(得分:1)

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

答案 6 :(得分:1)

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

答案 7 :(得分:0)

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

此方法还允许您从对象列表构建字符串结果 示例

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

这里的reduce函数允许你有一些你要追加新字符串的初始值 例如:

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

答案 8 :(得分:0)

测试Shail016bpedroso答案(https://stackoverflow.com/a/24883180/2832140)中建议的两种方法,即StringBuilder循环内的简单append(String) + for,似乎比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());
}

在我的开发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());
}

答案 9 :(得分:0)

我将使用streams api将整数流转换为单个字符串。某些提供的答案的问题在于,由于生成了String,它们会生成O(n ^ 2)运行时。更好的解决方案是使用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();

通过将对象的集合转换为单个字符串,可以使此过程更进一步。

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

答案 10 :(得分:-1)

我们可以尝试一下。

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

    }

答案 11 :(得分:-1)

使用Java 8 +

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

不是最有效的,但它是一个包含少量代码的解决方案。

答案 12 :(得分:-2)

另外,你可以这样做。

const Path = require('path');
const Webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
  devtool: '#eval-source-map',
  entry: [
    'babel-polyfill',
    Path.join(__dirname, '../../app/application/delegate'),
  ],
  output: {
    filename: 'bundle.js',
    path: Path.join(__dirname, '../public/'),
    publicPath: '/',
  },
  module: {
    loaders: [
      {
        test: /\.jsx$|\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        query: {
          presets: ['es2015', 'react', 'stage-2'],
          plugins: [['react-transform', {
            transforms: [{
              imports: ['react'],
              locals: ['module'],
              transform: 'react-transform-hmr',
            }],
          }]],
        },
      },
      {
        test: /\.css$/,
        use: ['css-hot-loader'].concat(ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: 'css-loader',
        })),
      },
      {
        test: /\.json$/,
        loader: 'json',
      },
    ],
  },
  plugins: [
    new Webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify('development'),
        PLATFORM_ENV: JSON.stringify('web'),
      },
    }),
    new Webpack.NoEmitOnErrorsPlugin(),
    new ExtractTextPlugin('styles.css'),
  ],
  resolve: {
    extensions: ['.js', '.jsx', '.json'],
  },
};