【问题标题】:Java Optimization String vs Char ArraysJava 优化字符串与字符数组
【发布时间】:2011-02-16 13:49:30
【问题描述】:

在我正在编写的程序中,我做了很多字符串操作。我正在尝试提高性能,并且想知道使用 char 数组是否会显示出不错的性能提升。有什么建议吗?

【问题讨论】:

  • @ThePinkPoo:您的问题缺乏要求:您的字符串应该包含什么? Unicode 的整个范围(在这种情况下,使用 char[] 将被证明是一个主要的痛苦,因为 Java charTOTALLY INADEQUATE 来表示引入的新 Unicode 代码点Unicode 3.1 及更高版本)?只有(一个子集)ASCII?在后一种情况下,您可以重新实现仅由字节支持的整个 String 类,并且可以完成很多 very 漂亮的优化。去过那里,做到了,用 Java 处理数百兆字节的 ASCII 文本文件......

标签: java arrays string optimization


【解决方案1】:

你在做什么操作?您可以发布代码示例吗?

您可能想查看实现CharSequence 以提高性能的StringBuilder。我不确定你想自己动手。顺便说一句,StringBuilder 不是线程安全的...如果您想要线程安全,请查看StringBuffer

【讨论】:

  • 如果您需要线程安全,那么您需要做的不仅仅是StringBuffer。您可能会避免死锁和竞争条件,但结果可能与您的预期不符。
  • 谢谢,我会重新实现,然后发布我的结果。
  • @Hank:通过一个重要的更新,您可以将自己的synchronized(thebuffer){...} 包裹起来,但您不需要太频繁地使用这种东西。确实,这就是引入StringBuilder 的原因;在不需要时(即几乎所有时间)完全消除持有锁的成本。
【解决方案2】:

这是 JDK 6.0 中full source of String class 的摘录:

 public final class String implements  java.io.Serializable,
       Comparable<String>, CharSequence {
       /** The value is used for character storage. */
        private final char value[];

       /** The offset is the first index of the storage that is used. */
       private final int offset;

        /** The count is the number of characters in the String. */
       private final int count;

正如您在内部看到的,该值已存储为字符数组。作为数据结构的字符数组具有大多数字符串操作的 String 类的所有限制:Java 数组不会增长,即每次(好吧,可能不是每次)你的字符串都需要增长你需要分配一个新数组并复制内容。

如前所述,对大多数字符串操作使用StringBuilderStringBuffer 是有意义的。

其实如下代码:

   String a = "a";
   a=a+"b";
   a=a+"c";

编译时会自动转换为使用StringBuilder,这可以在javap的帮助下轻松检查。

根据经验,花时间尝试提高核心 Java 类的性能是不可取的,除非您是这方面的世界级专家,因为这段代码最初是由世界级专家编写的地点。

【讨论】:

    【解决方案3】:

    String 已经实现为 char 数组。你打算做什么不同的事情?无论如何,如果您能找到一种通过替换 char 数组来提高性能的方法,那么在这与临时对象的 GC 非常快的事实之间,我会感到惊讶。

    Michael Borgwardt 关于小型 char 数组和使用 StringBuilder 和 StringBuffer 的建议非常好。但对我来说,最重要的是尽量不要猜测什么是慢的:进行测量,使用分析器,获得一些明确的事实。因为通常我们对性能的猜测被证明是错误的。

    【讨论】:

      【解决方案4】:

      您是否分析过您的应用程序?你知道瓶颈在哪里吗?如果性能低于标准,这是第一步。好吧,那就是定义什么是可接受的性能指标。

      一旦您对执行某些任务进行了概要分析,您将有一定百分比的时间花在做某事上。如果您花费大量时间来操作字符串,也许您可​​以开始缓存其中一些操作?当只做一次就足够了(然后在需要时再次使用该结果)时,您是否重复执行其中一些?您是否在不需要时复制字符串?请记住,java.lang.String 是不可变的 - 因此不能直接更改。

      我在优化/性能调整系统时发现了好几次,我本能地不知道缓慢来自哪里。我看到其他人(以及,可耻的是,我自己)花费数天时间优化没有任何收获的东西 - 因为它不是最初的瓶颈,实际上不到所花费时间的 1%。

      希望这有助于为您指明正确的方向。

      【讨论】:

      • 我已经进行了分析,但它并没有提供太多信息,因为我的复杂性非常小。我确实从配置文件中知道字符串方法正在杀死它,还有我在代码中的循环。所以我将展开一些循环并使用 StringBuilder
      • @ThePinkPoo:如果 String 操作正在扼杀它,那么最好的办法是尝试减少您正在执行的 String 操作的数量。这可以通过缓存或类似行​​为来完成。抱歉假设您没有配置文件 - 我经常在各种论坛样式页面(包括这里)上看到,并想确保您正在这样做。 :) 祝你好运。
      【解决方案5】:

      当你有大量的短字符串时,使用char[] 可以节省相当多的内存,这也意味着由于更少的缓存未命中而更快的速度。

      但是对于大字符串,要注意的主要事情是避免由于String 的不变性而导致的不必要的复制。如果你做了很多连接或替换,使用StringBuilder 可以产生很大的不同。

      【讨论】:

      • Michael,你能详细说明一下用 char[] 替换字符串吗? Char[] 将比 String 实例占用更少的空间,但是 char[] 不会被内部化,并且对于许多短字符串来说,一些字符串相同并且将被内部化的概率(即 JVM 将保留一个副本) 比几个长字符串要高得多。
      • @Totophil:这实际上取决于您使用哪种字符串以及如何使用它们;如果您使用可变表示,则实习变得无关紧要。
      • 迈克尔,同意,这真的取决于场景的具体情况。我想到的唯一场景是软件需要“就地”进行大量字符串操作。但是这种方法对于处理来自连接、搜索和比较的字符串开销没有任何帮助。
      猜你喜欢
      • 2011-08-20
      • 2014-12-15
      • 1970-01-01
      • 2010-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-16
      • 1970-01-01
      相关资源
      最近更新 更多