【问题标题】:Java equivalents of C# String.Format() and String.Join()C# String.Format() 和 String.Join() 的 Java 等效项
【发布时间】:2010-09-16 07:19:15
【问题描述】:

我知道这是一个新手问题,但有没有 C# 在 Java 中的字符串操作等价物?

具体来说,我说的是String.FormatString.Join

【问题讨论】:

标签: c# java string


【解决方案1】:

String.format。至于join,需要自己写:

 static String join(Collection<?> s, String delimiter) {
     StringBuilder builder = new StringBuilder();
     Iterator<?> iter = s.iterator();
     while (iter.hasNext()) {
         builder.append(iter.next());
         if (!iter.hasNext()) {
           break;                  
         }
         builder.append(delimiter);
     }
     return builder.toString();
 }

以上来自http://snippets.dzone.com/posts/show/91

【讨论】:

  • 更准确地说:StringBuffer 用于 jdk1.4 及以下,StringBuilder 用于 jdk1.5 及之后,因为后者不同步,因此速度更快。
  • 我通常不是两次 iter.hasNext() 调用,而是附加分隔符,然后“返回 buf.substring(0, buf.length() - delimeter.length())”。
  • 您可以通过提前退出来简化它以避免分隔符:while (true) ( add_iter; if (!iter.hasNext()) break; add_delim; }
【解决方案2】:

Java String 对象有一个format 方法(从1.5 开始),但没有join 方法。

要获得一些尚未包含的有用的字符串实用方法,您可以使用org.apache.commons.lang.StringUtils

【讨论】:

  • google 集合:google-collections.googlecode.com 也有一个 Joiner。
  • 关于 Ron 的评论仅供参考,google-collections 不久前被重命名为 Guava。
  • 您应该更新此答案以反映 Java 8 引入了 String.join() 方法。
【解决方案3】:

至于加入,我相信这看起来不那么复杂:

public String join (Collection<String> c) {
    StringBuilder sb=new StringBuilder();
    for(String s: c)
        sb.append(s);
    return sb.toString();
}

我没有尽可能多地使用 Java 5 语法(信不信由你,我最近一直在使用 1.0.x)所以我可能有点生疏,但我确信概念是正确的。

编辑添加:字符串追加可能会很慢,但是如果您正在处理 GUI 代码或一些短期运行的例程,那么您需要 0.005 秒还是 0.006 秒并不重要,所以如果您有一个名为"joinMe" 你想附加到一个现有的字符串 "target" 内联它不会是可怕的:

for(String s : joinMe)
    target += s;

这是非常低效的(也是一个坏习惯),但除非有数千个字符串,或者这是在一个巨大的循环中,或者您的代码对性能非常关键,否则您将无法感知到任何东西。

更重要的是,它易于记忆、简短、快速且易读。性能并不总是设计选择的自动赢家。

【讨论】:

  • for 循环是正确的,但您也应该将其设为 Collection。如果你不这样做,你就不得不说“for (Object o : c)”,因为你不能保证 c 中的所有东西都是一个字符串。
  • 好点,我对泛型更加生疏了。我会编辑它。
  • 当concat inline: string + string + string时,编译器实际上使用StringBuilder来追加值。我想知道在 for-loop 方法中是否有第二个,编译器是否会这样做。
  • @Spencer K:它确实使用了 StringBuilder,但它为每次迭代创建一个新的(几乎不是最有效的方法,但是编译器应该如何知道呢?)。我不知道 JIT 编译器是否会在运行时对其进行优化。
  • 哦-等等。你说的是+=?是的,这很糟糕。我的答案中当前的循环和附加使用 StringBuilder ,这就是我所说的。虽然 += 已经改进了很多,但你真的不想在循环中使用它——与其说它是错误的,不如说它可以像垃圾一样执行(错误不是通常用于性能问题的术语——至少不是在我 20 年的编程生涯中)。 JIT 也可以极大地改善这一点——但我不会依赖它。
【解决方案4】:

如果您希望将多个字符串连接(连接)为一个,则应使用 StringBuilder。这比使用

好得多
for(String s : joinMe)
    target += s;

由于 StringBuilder 不使用同步,因此性能也比 StringBuffer 略有优势。

对于像这样的通用实用程序方法,它会(最终)在很多情况下被多次调用,所以你应该让它高效而不是分配很多瞬态对象。我们分析了许许多多不同的 Java 应用程序,并且几乎总是发现字符串连接和字符串/char[] 分配占用了大量的时间/内存。

我们的可重用集合 -> 字符串方法首先计算所需结果的大小,然后创建一个具有该初始大小的 StringBuilder;这避免了附加字符串时使用的内部 char[] 不必要的加倍/复制。

【讨论】:

  • re:预先计算大小:当它工作时,它很棒。这并不总是可能的。我记得在某处读过,每次将缓冲区大小加倍(或实际上乘以任何固定因子)会产生类似 n log n 的性能,这并不是那么糟糕。在一般情况下,另一种方法是列出您计划连接的所有字符串。如果您使用 ArrayList,您将再次进行复制(除非您事先知道序列的长度),如果您使用 LinkedList,那么它会使用更多的 ram 和对节点对象进行垃圾收集。有时你赢不了。试试看!
  • 上述示例/查询假设要加入一些有序集合或字符串数​​组。此外,通过预先计算大小,您可以避免内部 char[] 数组增长通常导致的额外未使用字符。
【解决方案5】:

StringUtils 是 Apache Commons Lang 库中一个非常有用的类。

【讨论】:

【解决方案6】:

我只想使用字符串连接运算符“+”来连接两个字符串。 s1 += s2;

【讨论】:

  • 因为这是不好的做法而且速度很慢。
【解决方案7】:

您还可以对字符串使用可变参数,如下所示:

  String join (String delim, String ... data) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < data.length; i++) {
      sb.append(data[i]);
      if (i >= data.length-1) {break;}
      sb.append(delim);
    }
    return sb.toString();
  }

【讨论】:

    【解决方案8】:

    Guava 附带the Joiner class

    import com.google.common.base.Joiner;
    
    Joiner.on(separator).join(data);
    

    【讨论】:

      【解决方案9】:

      我自己写的:

      public static String join(Collection<String> col, String delim) {
          StringBuilder sb = new StringBuilder();
          Iterator<String> iter = col.iterator();
          if (iter.hasNext())
              sb.append(iter.next().toString());
          while (iter.hasNext()) {
              sb.append(delim);
              sb.append(iter.next().toString());
          }
          return sb.toString();
      }
      

      但是JSP不支持Collection,所以对于标签功能我写了:

      public static String join(List<?> list, String delim) {
          int len = list.size();
          if (len == 0)
              return "";
          StringBuilder sb = new StringBuilder(list.get(0).toString());
          for (int i = 1; i < len; i++) {
              sb.append(delim);
              sb.append(list.get(i).toString());
          }
          return sb.toString();
      }
      

      并放入.tld文件:

      <?xml version="1.0" encoding="UTF-8"?>
      <taglib version="2.1" xmlns="http://java.sun.com/xml/ns/javaee"
          <function>
              <name>join</name>
              <function-class>com.core.util.ReportUtil</function-class>
              <function-signature>java.lang.String join(java.util.List, java.lang.String)</function-signature>
          </function>
      </taglib>
      

      并在 JSP 文件中将其用作:

      <%@taglib prefix="funnyFmt" uri="tag:com.core.util,2013:funnyFmt"%>
      ${funnyFmt:join(books, ", ")}
      

      【讨论】:

        【解决方案10】:

        TextUtils.join 在 Android 上可用

        【讨论】:

          【解决方案11】:
          ArrayList<Double> j=new ArrayList<>; 
          j.add(1);
          j.add(.92);
          j.add(3); 
          String ntop=j.toString(); //ntop= "[1, 0.92, 3]" 
          

          所以基本上,String ntop 用逗号分隔符和方括号存储整个集合的值。

          【讨论】:

          • 我不确定这回答了问题的哪一部分?它不是 String.format 除非您打算将字符串的位逐位添加到数组中,并且 [1,0.92,3] 不如通用字符串 .join 通用。
          【解决方案12】:

          从 Java 8 开始,join() 现在可用作 String 类的两个类方法。在这两种情况下,第一个参数都是分隔符。

          你可以pass individual CharSequences as additional arguments:

          String joined = String.join(", ", "Antimony", "Arsenic", "Aluminum", "Selenium");
          // "Antimony, Arsenic, Alumninum, Selenium"
          

          或者你可以pass an Iterable&lt;? extends CharSequence&gt;:

          List<String> strings = new LinkedList<String>();
          strings.add("EX");
          strings.add("TER");
          strings.add("MIN");
          strings.add("ATE");
          
          String joined = String.join("-", strings);
          // "EX-TER-MIN-ATE"
          

          Java 8 还添加了一个新类 StringJoiner,您可以像这样使用它:

          StringJoiner joiner = new StringJoiner("&");
          joiner.add("x=9");
          joiner.add("y=5667.7");
          joiner.add("z=-33.0");
          
          String joined = joiner.toString();
          // "x=9&y=5667.7&z=-33.0"
          

          【讨论】:

            【解决方案13】:

            我不想导入整个 Apache 库来添加简单的连接函数,所以这是我的 hack。

                public String join(String delim, List<String> destinations) {
                    StringBuilder sb = new StringBuilder();
                    int delimLength = delim.length();
            
                    for (String s: destinations) {
                        sb.append(s);
                        sb.append(delim);
                    }
            
                    // we have appended the delimiter to the end 
                    // in the previous for-loop. Let's now remove it.
                    if (sb.length() >= delimLength) {
                        return sb.substring(0, sb.length() - delimLength);
                    } else {
                        return sb.toString();
                    }
                }
            

            【讨论】:

            • @MrSnowflake 标准字符串生成器是否有一个方法“removeCharAt(int index)”它没有显示在我正在运行的版本上
            • @NSjonas - 是的,他对我的回答的编辑是错误的。 removeCharAt 不存在,整个函数不再返回字符串...将解决此问题。
            • 当你在它的时候......这个当前的解决方案将抛出一个“如果你传入一个空列表,则索引越界异常”
            • 进行了编辑以在分隔符超过 1 个字符时修剪正确的长度。还修复了您正在修剪最后一个字符而不是第一个字符的问题,因为您确实需要
            • 感谢您的反馈。已更新。
            【解决方案14】:

            这是一个非常简单的答案。使用+=,因为它的代码更少,让优化器为您将其转换为StringBuilder。使用这种方法,您不必在循环中执行任何“最后一次”检查(性能改进),并且您不必担心在末尾剥离任何分隔符。

                    Iterator<String> iter = args.iterator();
                    output += iter.hasNext() ? iter.next() : "";
                    while (iter.hasNext()) {
                        output += "," + iter.next();
                    }
            

            【讨论】:

            • 非常优雅的解决方案,不涉及第三方库!
            【解决方案15】:

            MessageFormat.format() 与 C# 的 String.Format() 类似。

            【讨论】:

              【解决方案16】:

              我在这里看到了很多过于复杂的 String.Join 实现。如果您没有 Java 1.8,并且不想导入新库,则以下实现就足够了。

              public String join(Collection<String> col, String delim) {
                  StringBuilder sb = new StringBuilder();
                  for ( String s : col ) {
                      if ( sb.length() != 0 ) sb.append(delim);
                      sb.append(s);
                  }
                  return sb.toString();
              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-01-29
                • 2010-11-17
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多