有效地连接嵌套列表中的文本

时间:2018-02-07 20:44:31

标签: java lambda java-8

假设我有一个文本表示为单词行的集合。我希望将单词与空格连接在一起,并使用换行符连接行:

class Word {
  String value;
}

public static String toString(List <List <Word>> lines) {
    return lines.stream().map(
            l -> l.stream().map(w -> w.value).collect(Collectors.joining(" "))
    ).collect(Collectors.joining("\n"));
}

这很好用,但我最终为每一行创建了一个中间String对象。在没有开销的情况下,有没有一种简洁的方法来做同样的事情?

2 个答案:

答案 0 :(得分:5)

 String s = List.of(
            List.of(new Word("a"), new Word("b")),
            List.of(new Word("c"), new Word("d")),
            List.of(new Word("e"), new Word("f")))
            .stream()
            .collect(Collector.of(
                    () -> new StringJoiner(""),
                    (sj, list) -> {
                        list.forEach(x -> sj.add(x.getValue()).add(" "));
                        sj.add("\n");
                    },
                    StringJoiner::merge,
                    StringJoiner::toString));

修改

我可以解决这个问题,但不能告诉你是否同意额外的冗长与创建该字符串:

.stream()
.collect(Collector.of(
          () -> new StringJoiner(""),
          (sj, list) -> {
              int i;
              for (i = 0; i < list.size() - 1; ++i) {
                 sj.add(list.get(i).getValue()).add(" ");
              }
              sj.add(list.get(i).getValue());
              sj.add("\n");
          },
          StringJoiner::merge,
          x -> {
              String ss = x.toString();
              return ss.substring(0, ss.length() - 1);
          }));

答案 1 :(得分:3)

您可以使用

public static String toString(List<List<Word>> lines) {
    return lines.stream()
        .map(l -> l.stream()
                   .map(w -> w.value)
                   .collect(() -> new StringJoiner(" "),
                            StringJoiner::add,
                            StringJoiner::merge))
        .collect(() -> new StringJoiner("\n"),
                       StringJoiner::merge,
                       StringJoiner::merge).toString();
}

内部collect基本上执行Collectors.joining(" ")所做的事情,但省略了最后的StringJoiner.toString()步骤。

然后,外部collect与普通Collectors.joining("\n")的不同之处在于它接受StringJoiner作为输入并使用merge组合它们。这取决于a documented behavior

  

如果另一个StringJoiner使用不同的分隔符,则另一个StringJoiner中的元素与该分隔符连接,结果作为单个元素附加到此StringJoiner。< / p>

这是在StringBuilder /字符数据级别内部完成的,无需创建String实例,同时保留预期的语义。