将Set <String>的内容放到单个字符串中且单词之间用空格隔开的最快方法?


76

我有几个Set<String>s,并且想要将它们中的每一个转换成单个String,其中原始元素的每个元素Set都由空格“”分隔。天真的第一方法就是这样做

Set<String> set_1;
Set<String> set_2;

StringBuilder builder = new StringBuilder();
for (String str : set_1) {
  builder.append(str).append(" ");
}

this.string_1 = builder.toString();

builder = new StringBuilder();
for (String str : set_2) {
  builder.append(str).append(" ");
}

this.string_2 = builder.toString();

谁能想到更快,更漂亮或更有效的方式来做到这一点?


Answers:


141

使用commons / lang可以使用StringUtils.join来做到这一点:

String str_1 = StringUtils.join(set_1, " ");

为了简洁起见,您无法真正击败它。

更新:

重新阅读此答案,我希望使用有关番石榴木匠的其他答案。实际上,这些天我不接近apache commons。

另一个更新:

Java 8引入的方法 String.join()

String joined = String.join(",", set);

尽管它不像Guava版本那样灵活,但是当您的类路径中没有Guava库时,它很方便。


2
简短但不灵活。无论我是否想要,我都会用“”代替null,并且没有“跳过null”选项...这就是为什么我们制作了番石榴的Joiner(请参见其他答案)的原因。
凯文·布瑞里恩

通常,我的收藏夹中没有空值,因此简短的方法对我来说很好,但是番石榴却很糟糕!感谢您实现了这一目标……
肖恩·帕特里克·弗洛伊德

由于您不希望空值,因此,如果您确实有空值,则希望您的细木工会崩溃-这是Guava的细木工默认情况下所做的。:-)
Kevin Bourrillion 2010年

1
@ smp7d也不应该。空无效输入。假设这将是危险的。通过前提条件检查来拒绝空值,您将不必再担心空安全性
肖恩·帕特里克·弗洛伊德

1
@SeanPatrickFloyd Hmm,阅读有趣,感谢您的参考。我通常会非常谨慎,故意并且尽量少使用null,因此也许我没有注意到太多。最重要的不过,我总是一直总是检查空值/参数使用前抛出一个异常,如果是这样,在几乎所有情况下..
Java的addict301

31

如果您使用的是Java 8,则可以使用本

String.join(CharSequence delimiter, Iterable<? extends CharSequence> elements)

方法:

返回一个新StringCharSequence元素,该元素由与指定定界符的副本连接在一起的元素的副本组成。例如:

 Set<String> strings = new LinkedHashSet<>();
 strings.add("Java"); strings.add("is");
 strings.add("very"); strings.add("cool");
 String message = String.join("-", strings);
 //message returned is: "Java-is-very-cool"

Set实现Iterable,因此只需使用:

String.join(" ", set_1);

21

作为对Seanizer的commons-lang答案的反驳,如果您使用的是Google的Guava库(在很多方面,我认为它是commons-lang的“后继者”),则可以使用Joiner

Joiner.on(" ").join(set_1);

借助一些辅助方法的优势来执行以下操作:

Joiner.on(" ").skipNulls().join(set_1);
// If 2nd item was null, would produce "1, 3"

要么

Joiner.on(" ").useForNull("<unknown>").join(set_1);
// If 2nd item was null, would produce "1, <unknown>, 3"

它还支持直接附加到StringBuilders和Writers以及其他类似功能。


番石榴库和Google收藏库有什么区别?
Shervin Asgari 2010年

主要区别在于番石榴不了解泛型和公共/集合,但除此之外:它们是由两个不同的团队编写的两个不同的库,使用不同的方法解决了一些相似的问题(和一些非相似的问题)
Sean帕特里克·弗洛伊德(Patrick Floyd)2010年

2
@ seanizer,Shervin询问的是番石榴vs谷歌收藏,而不是番石榴vs普通品:) Shervin-番石榴只是Google收藏的替代品。随着项目范围的扩大,它不再局限于仅限收藏的事物,因此按顺序进行了名称更改。基本上应将google-collection视为已弃用,guava是具有bug修复+更多功能的嵌入式替代品。
考恩

7

我没有可用的StringUtil库(对此我别无选择),因此使用标准Java我提出了这个..

如果您确信您的设置数据不会包含任何逗号或方括号,则可以使用:

mySet.toString().replaceAll("\\[|\\]","").replaceAll(","," ");

一组“ a”,“ b”,“ c”通过.toString()转换为字符串“ [a,b,c]”。

然后根据需要替换多余的标点符号。

污秽。


2
真好!总是很高兴看到您可以使用JDK标准库做什么:)
Lars Andren

干净,简单,不依赖库,因此不会增加应用程序的重量-喜欢它!
Lukas Novicky

1
...,只要您的集合中没有任何“ [”或“]”即可;)
Tedil

我已经提到过逗号,但是您对[和]也很正确。更新了答案。
user2808054

1
遗憾的是,有些人没有Java8 +,并且无法轻松访问库。这样的答案对那些人很有帮助。
lewdev

6

也许是一个较短的解决方案:

public String test78 (Set<String> set) {
    return set
        .stream()
        .collect(Collectors.joining(" "));
}

要么

public String test77 (Set<String> set) {
    return set
        .stream()
        .reduce("", (a,b)->(a + " " + b));
}

但是原生,绝对更快

public String test76 (Set<String> set) {
    return String.join(" ", set);
}

4

我使用这种方法:

public static String join(Set<String> set, String sep) {
    String result = null;
    if(set != null) {
        StringBuilder sb = new StringBuilder();
        Iterator<String> it = set.iterator();
        if(it.hasNext()) {
            sb.append(it.next());
        }
        while(it.hasNext()) {
            sb.append(sep).append(it.next());
        }
        result = sb.toString();
    }
    return result;
}

2

我对代码复制感到困惑,为什么不将其分解为一个需要一组并返回一个字符串的函数呢?

除此之外,我不确定您可以做很多事情,除了可能为stringbuilder提供有关预期容量的提示(如果您可以根据设置的大小和合理的字符串长度预期进行计算)。

也有用于此的库函数,但我怀疑它们的效率明显更高。


感谢您的回答!我没有将其放在单独的函数中来强调这一事实,即我试图重用“ builder”变量。也许没关系吗?
拉尔斯·安德伦

3
没关系 重新使用变量实际上会使您陷入困境。取而代之的是,使变量不再需要时超出范围。
Gunslinger47年

@Gunslinger,我明白了,谢谢!@Uri,感谢您的初始容量提示。
拉尔斯·安德伦

1
@Lars,在某些情况下重用是有意义的,但在其他情况下,最好转储并从头开始。我不确定这里有什么更好的。您可以编写一个具有共享的实例变量构建器的实用程序类。每次运行一个构建器的一个优点是,您可以与多个线程并行转换大量的集合。
乌里(Uri)

2

这可以通过在集合之外创建流,然后使用reduce操作组合元素来完成,如下所示(有关Java 8流的更多详细信息,请参见此处):

Optional<String> joinedString = set1.stream().reduce(new 
BinaryOperator<String>() {

     @Override
     public String apply(String t, String u) {

       return t + " " + u;
    }
});
return joinedString.orElse("");
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.