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

yka*_*ich 5 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"));
}
Run Code Online (Sandbox Code Playgroud)

这工作正常,但我最终为每一行创建一个中间String对象.在没有开销的情况下,是否有一种非常简洁的方法来做同样的事情?

Eug*_*ene 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));
Run Code Online (Sandbox Code Playgroud)

编辑

我可以做到这一点,但不能告诉你是否同意额外的冗长与创建该字符串:

.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);
          }));
Run Code Online (Sandbox Code Playgroud)


Hol*_*ger 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();
}
Run Code Online (Sandbox Code Playgroud)

内部collect基本上做了什么Collectors.joining(" "),但省略了最后StringJoiner.toString()一步。

然后,外部collect与普通的不同Collectors.joining("\n")之处在于它接受StringJoiner输入并使用 组合它们merge。这依赖于记录的行为

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

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