将 Set<String> 的内容放入单个字符串的最快方法,其中单词用空格分隔?

Posted

技术标签:

【中文标题】将 Set<String> 的内容放入单个字符串的最快方法,其中单词用空格分隔?【英文标题】:Fastest way to put contents of Set<String> to a single String with words separated by a whitespace? 【发布时间】:2010-06-15 01:45:18 【问题描述】:

我有几个Set&lt;String&gt;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();

谁能想到一种更快、更漂亮或更有效的方法来做到这一点?

【问题讨论】:

***.com/questions/187676/string-operations-in-java 【参考方案1】:

使用 commons/lang 你可以使用StringUtils.join:

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

为了简洁,你真的无法击败它。

更新:

重新阅读这个答案,我现在更喜欢the other answer regarding Guava's Joiner。事实上,这些天我并没有靠近 apache commons。

另一个更新:

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

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

虽然这不如 Guava 版本灵活,但当您的类路径中没有 Guava 库时,它会很方便。

【讨论】:

简短,但不灵活。无论我是否愿意,我都会将 "" 替换为 null,并且没有跳过 nulls 选项...这就是我们为 Guava 制作 Joiner 的原因(请参阅其他答案)。 我的收藏中通常没有空值,所以简短的方法对我来说很好,但番石榴摇滚!感谢您让这一切发生... 由于您不期望空值,如果您确实有一个空值,您希望您的连接器爆炸——这是 Guava 的连接器默认执行的操作。 :-) @smp7d 也不应该。 Null 不是有效的输入。假设它是危险的。使用前置条件检查拒绝 null 值,您再也不必担心 null 安全性 @SeanPatrickFloyd 嗯,读起来很有趣,感谢您的参考。一般来说,我对 null 的使用非常小心、故意和最小化,所以也许我没有注意到太多。然而最重要的是,在几乎所有情况下,我总是总是在使用前检查值/参数是否为 null,如果是,则抛出异常..【参考方案2】:

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

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

方法:

返回一个新的String,该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);

【讨论】:

【参考方案3】:

作为与 Seanizer 的 commons-lang 答案的对立面,如果您使用 Google 的 Guava Libraries(在很多方面我认为它是 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,以及其他类似的细节。

【讨论】:

guava-libraries和google collection library有什么区别? 主要区别在于 guava 知道泛型和 commons/collections 不知道,但除此之外:它们是两个不同的库,由两个不同的团队编写,解决一些类似的问题(以及一些非类似的)使用不同的方法 @seanizer,Shervin 询问的是 guava vs google-collections,而不是 guava vs commons :) Shervin - guava 只是 google-collections 的替代品。随着项目范围的扩大,它不再仅限于收藏品,因此更改名称是必要的。 google-collections 基本上应该被视为已弃用,guava 是具有错误修复和更多功能的直接替代品。【参考方案4】:

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

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

【讨论】:

【参考方案5】:

我没有可用的 StringUtil 库(我别无选择)所以使用标准 Java 我想出了这个..

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

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

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

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

污秽。

【讨论】:

不错!看到你可以用 JDK 标准库做什么总是很酷:) 干净、简单、不依赖库,因此不会增加应用程序的重量 - 喜欢它! ...当然,只要您的集合中没有任何“[”或“]”或“,”;) 遗憾的是,有些人没有 Java8+,也无法轻松访问库。像这样的答案对这些人非常有帮助。 小心。如果 toString 被覆盖,它可能不起作用。【参考方案6】:

我用这个方法:

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;

【讨论】:

【参考方案7】:

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

除此之外,我不确定您可以做很多事情,除了可能向字符串生成器提供有关预期容量的提示(如果您可以根据集合大小和字符串长度的合理期望来计算它)。

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

【讨论】:

感谢您的回答!我没有把它放到一个单独的函数中来强调我正在尝试重用“builder”变量的事实。也许这没关系? 没关系。重新利用变量实际上会给你带来麻烦。相反,只需在不再需要变量时让变量超出范围即可。 @Gunslinger,我明白了,谢谢! @Uri,感谢您提供初始容量提示。 @Lars,在某些情况下重用是有意义的,但在其他情况下,最好转储并从头开始。我不确定这里有什么更好的。您可以编写一个实用程序类,该类具有一个共享的实例变量构建器。每次运行一个构建器的一个优点是您可以使用多个线程并行转换大量集合。​​【参考方案8】:

这可以通过从集合中创建一个流然后使用 reduce 操作组合元素来完成,如下所示(有关 Java 8 流的更多详细信息,请查看here):

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

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

       return t + " " + u;
    
);
return joinedString.orElse("");

【讨论】:

以上是关于将 Set<String> 的内容放入单个字符串的最快方法,其中单词用空格分隔?的主要内容,如果未能解决你的问题,请参考以下文章

快速将填充的 Set<String> 转换为 [String] [重复]

Java流和分组:将对象放入多个组[重复]

将 HashMap<String, object> 放入 jsonobject

Java 将 Map<String,Set<String>> 转换为 Map<String,Set<Object1>> [关闭]

如何将设置数据类型放入Firestore?

C#中List<List<string>>要怎么处理?