【问题标题】:Why StringJoiner when we already have StringBuilder?既然我们已经有了 StringBuilder,为什么还要使用 StringJoiner?
【发布时间】:2015-02-15 19:44:39
【问题描述】:

我最近遇到了一个 Java 8 类 StringJoiner,它使用分隔符添加字符串并为其添加前缀和后缀,但我无法理解此类的需要,因为它还在后端使用 StringBuilder并且还执行非常简单的附加字符串操作。

我是不是因为没有真正理解这门课的真正目的而错过了什么?

【问题讨论】:

  • 实现简单并不排除作为一个类单独执行时有用。尤其是考虑到多久应用程序程序员必须手动(或通过第 3 方库)进行类似操作。

标签: java string java-8 stringbuilder


【解决方案1】:

StringJoiner 非常有用,当您需要在Stream 中加入字符串时。

例如,如果您必须遵循字符串列表:

final List<String> strings = Arrays.asList("Foo", "Bar", "Baz");

使用起来更简单

final String collectJoin = strings.stream().collect(Collectors.joining(", "));

就像StringBuilder 一样:

final String collectBuilder =
    strings.stream().collect(Collector.of(StringBuilder::new,
        (stringBuilder, str) -> stringBuilder.append(str).append(", "),
        StringBuilder::append,
        StringBuilder::toString));

6 年后编辑 正如 cmets 中所述,现在有更简单的解决方案,例如 String.join(", ", strings),当时还没有这些解决方案。但是用例还是一样的。

【讨论】:

  • 请注意,这两个示例相同!第一个生成字符串"foo, Bar, Baz",第二个生成"foo, Bar, Baz, "
  • @PaulWagland 是的,这就是.joining 的额外美感。通常,您不需要最后一个逗号...
  • @Koshinae 完全同意,在流式传输的情况下修复它也会使已经很复杂的语句变得更加复杂!
  • String.join(", ", strings)strings.stream().collect(Collectors.joining(", ")) 的更快版本
  • 怎么样:list.stream().map(Util::quote).collect(Collectors.joining(","))
【解决方案2】:

StringJoiner Javadoc 上的示例非常擅长涵盖这一点。整个要点是从添加条目的行为中抽象出分隔符的选择。例如您可以创建一个连接器,指定要使用的分隔符并将其传递给库以添加元素,反之亦然。

字符串“[George:Sally:Fred]”可以如下构造:

StringJoiner sj = new StringJoiner(":", "[", "]");
sj.add("George").add("Sally").add("Fred");
String desiredString = sj.toString();

StringJoiner 可用于使用 Collectors.joining(CharSequence) 从 Stream 创建格式化输出。例如:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
String commaSeparatedNumbers = numbers.stream()
    .map(i -> i.toString())
    .collect(Collectors.joining(", "));

【讨论】:

  • Peter,您对 StringBuilder 与 StringJoiner 的性能进行了基准测试吗?从这方面来说,你更喜欢哪一个?
  • @Simeon 如果我想要在我附加的每个内容之间使用隐式分隔符,我会使用字符串连接器,如果不是,则使用字符串构建器。这与性能无关,而是使期望的操作更清晰。
【解决方案3】:

它可能会在某些用例中简化您的代码:

List<String> list = // ...;

// with StringBuilder
StringBuilder builder = new StringBuilder();
builder.append("[");
if (!list.isEmpty()) {
    builder.append(list.get(0));
    for (int i = 1, n = list.size(); i < n; i++) {
        builder.append(",").append(list.get(i));
    }
}
builder.append("]");

// with StringJoiner
StringJoiner joiner = new StringJoiner(",", "[", "]");
for (String element : list) {
    joiner.add(element);
}

【讨论】:

  • 如果 StringJoiner 有一个接收 List 或 Collection 的方法并在内部进行迭代 + 添加每个元素,那就太好了。
【解决方案4】:

StringJoiner 是一种收集器,尽管它没有实现Collector 接口。它只是表现得如此。除了可以传递分隔符、前缀和后缀之外,StringJoiner 还可以用于从 Stream 调用 Collectors.joining(CharSequence) 创建格式化输出。

这在处理并行流时特别有用,因为在某些时候并行处理的批次需要加入,这就是@ 987654326@ 发生。

【讨论】:

  • 不完全是。它是一个适合在 Collector 中使用的低级实用程序组件(joining() 实际上确实使用它),但也适用于 Streams 世界之外。人们一直在编写这类循环。
【解决方案5】:

StringJoiner 比使用 StringBuilder 简单得多。一个很简单的代码就像

StringJoiner sj = new StringJoiner(",");
        sj.add("aaa");
        sj.add("bbb");
        sj.add("ccc");
        String result = sj.toString(); //aaa,bbb,ccc

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-18
    • 1970-01-01
    • 1970-01-01
    • 2019-10-31
    • 2017-11-13
    • 1970-01-01
    • 1970-01-01
    • 2016-02-04
    相关资源
    最近更新 更多