【问题标题】:Char Array vs String: which is better for storing a set of lettersChar Array vs String:哪个更适合存储一组字母
【发布时间】:2009-04-29 10:33:32
【问题描述】:

我需要在一个常量类 4 字母中存储一个代码。我能做到:

static final String CODE_LETTERS = "TRWAG";

或

static final char[] CODE_LETTERS = {'T', 'R', 'W', 'A', 'G'};

之后,我可以通过两种方式获得其中一个字符:

final char codeLetter = CODE_LETTERS.charAt(index);

或

final char codeLetter = CODE_LETTERS[index];

什么是最好的方法?请注意修正、性能等。

【问题讨论】:

  • 看起来像 5 个字母 :)

标签: java performance coding-style constants


【解决方案1】:

两者都不正确,但由于您要单独处理chars,我个人会使用char []。也就是说,即使可以衡量,这对性能的影响也将是微不足道的。

【讨论】:

    【解决方案2】:

    在这种情况下,性能无关紧要。如果它真的应该保持不变,则不能使用 char[] 方法。考虑:

    public class Test
    {
      static final char[] CODE_LETTERS = {'T', 'R', 'W', 'A', 'G'};
    
      public static void main(String[] args) throws Exception
      {
        System.out.println(CODE_LETTERS[0]); // T
        CODE_LETTERS[0] = 'x';
        System.out.println(CODE_LETTERS[0]); // x
      }
    }
    

    【讨论】:

    • 谁说性能无关紧要?许多人在性能上花费了很多精力。当然,实现可以做一些调皮的事情,但是如果表示是本地化的,我们可以说“不要那样做”。
    • 我的意思是这不是性能问题,因为 char[] 版本甚至无法按预期工作。让我们集中精力纠正这种情况下的明显错误:过早优化,并使用数组作为常量。
    • 我在上面的交流之后编辑了我的答案并添加了“在这种情况下”限定词。我在这里提到它是为了避免让读者过于困惑。
    【解决方案3】:

    除非您要连续数百万次获取角色,否则您无需担心性能。

    【讨论】:

    • 我的想法完全正确。说真的:过早的优化是万恶之源。
    • 但同样不应过早悲观。对于固定长度的不可变字符串,char 数组总是比等效的 std::string 对象更快并且内存开销更少。
    • 这很可能是需要多次完成的事情。如果这是java.lang.String 实现中的一种新方法呢?
    【解决方案4】:

    字符串是不可变的,char[] 不是。如果您将其定义为类中的公共“常量”,则 String 是真正的常量。

    例如,如果你有这个:

    public class MyClass { 
        public static final char[] CODE_LETTERS = {'h', 'e', 'l', 'l', 'o'};
        ....
    }
    

    我可以偷偷摸摸地这样做:

    MyClass.CODE_LETTERS[0] = 'Q';
    

    Bam,我改变了你的“常数”的值。

    final 关键字只影响对数组的引用,它不适用于数组元素。我一直在Collections.unmodifiableList() 看到类似的错误,人们认为它保护了他们的列表,但客户端代码仍然可以访问和修改列表元素。

    所以要回答您的问题,请使用字符串。

    【讨论】:

      【解决方案5】:

      这几乎可以肯定是过早的优化。如果您需要将其提供给其他方法,则使用字符数组在性能上节省的任何内容都可能会丢失可读性,因为接受 String 而不是 char[] 更为规范。

      【讨论】:

        【解决方案6】:

        String 的含义确实匹配一组char。所以char[]作为一个实现,虽然没有设置含义,但不会添加String的额外含义。 OTOH,您可能会在String 中找到有用的方法。第三方面,java.util.Arrays 也有 [binarySearch][2] 等有用的方法。

        也许您想要做的是为一组char 引入一个抽象,这可能会在使用String 作为可能工作的最简单的char[] 的线性扫描(如果你不这样做的话很快) t 扫描很远),二进制搜索,位设置。稀疏位集、散列、泛洪过滤等。

        [2]:http://java.sun.com/javase/6/docs/api/java/util/Arrays.html#binarySearch(char[], int, int, char)

        【讨论】:

          【解决方案7】:

          由于字符串使用 char[] 来保存您的字母,因此真正的答案是 char[] 更快。如果有疑问,请查看源代码,String 中没有任何魔力,它只是像任何其他类一样使用 int 和 char[] 之类的原语。

          你真的不应该关心这种微不足道的事情。在程序中发生了更多的事情,担心单个字符串是否比使用 char 数组更快。

          【讨论】:

          • 是的,但是当一个字符串在语义上被用作一个字符串而不是一个字符数组时,那么应该使用字符串。在 Java 中使用 char[] 仅在您想要处理单个字符项或需要频繁替换数组位置时才有意义。
          【解决方案8】:

          您会看到字符串和字符数组之间的性能差异的唯一一次是在探查器下,然后只是因为探查器会做错事。现代 JVMS (JDK 6+) 将在 JVM 确定这足够热以进行优化时为这两个访问生成相同的代码。

          回答你的问题;如果您使用的是 Java 5,请使用枚举,如果您使用的是 Java5 之前的版本,请使用 Java enumeration Pattern。

          这将使您的代码更具可读性,因为您无需在某处跟踪偏移量,您只需使用枚举即可。此外,它会更快,因为您将能够执行以下操作:

          
            final char codeLetter = enum.getCodeLetter(); 
          

          【讨论】:

          • 没有迹象表明 enum 是他想要的。如果他打算在某处将字符用作字符,那么将它们存储为枚举是没有意义的。
          • 如果枚举值为 T、R、W、A、G,则可以使用 toString()。
          【解决方案9】:

          看来您应该考虑使用 枚举。 见Enum Types

          【讨论】:

          • 在不知道有什么用途的情况下,这不是一个好建议。如果他要将角色与其他角色进行比较,那么枚举没有意义。
          【解决方案10】:

          有趣的是,我昨天刚刚写了一封blog entry 讨论这个问题。你需要一个围绕 char[] 的特殊类。我的Characters 类是一种保持不可变字符集的轻量级方法,并为诸如搜索之类的事情提供了高效的方法。它是开源的。

          【讨论】:

          • 你的班级会根据建筑对他的角色进行排序,所以它并不能真正回答他的问题,但我喜欢班级背后的理念。如果我可以单独为您的博客文章 +1,我会的。
          • @ahcox,谢谢你的好话。我已经在我的博客网站中添加了 Facebook 的“点赞”功能,所以请随意尝试一下! ;)
          猜你喜欢
          • 2015-06-07
          • 1970-01-01
          • 1970-01-01
          • 2015-01-19
          • 2011-02-10
          • 1970-01-01
          • 2014-06-06
          • 2019-03-05
          • 2012-05-15
          相关资源
          最近更新 更多