【问题标题】:Java: Efficient way to determine if a String meets several criteria?Java:确定字符串是否满足多个标准的有效方法?
【发布时间】:2012-10-17 13:36:29
【问题描述】:

我想找到一种高效的方式(不扫描字符串10,000次,或者创建大量中间字符串来保存临时结果,或者字符串抨击等)来编写一个接受的方法一个字符串,并确定它是否满足以下条件:

  • 长度至少为 2 个字符
  • 第一个字符是大写的
  • 第一个字符之后的剩余子字符串至少包含 1 个小写字符

这是我目前的尝试:

private boolean isInProperForm(final String token) {
    if(token.length() < 2)
        return false;

    char firstChar = token.charAt(0);
    String restOfToken = token.substring(1);
    String firstCharAsString = firstChar + "";
    String firstCharStrToUpper = firstCharAsString.toUpperCase();

    // TODO: Giving up because this already seems way too complicated/inefficient.
    // Ignore the '&& true' clause - left it there as a placeholder so it wouldn't  give a compile error.
    if(firstCharStrToUpper.equals(firstCharAsString) && true)
        return true;

    // Presume false if we get here.
    return false;
}

但正如您所见,我已经有 1 个 char 和 3 个临时字符串,但感觉有些不对劲。一定有更好的方法来写这个。这很重要,因为此方法将被调用数千次(对于文本文档中的每个标记化单词)。所以它真的需要高效。

提前致谢!

【问题讨论】:

  • 为什么不试试StringBuilder
  • 如果它只会被调用数千次(相对于数百万或数十亿),在它成为问题之前不要担心效率。
  • 如果删除 &amp;&amp; true 会产生编译时错误,那么问题就更大了……
  • @RohitJain:实际上这里不需要任何字符串。
  • 使用正则表达式,直到您测量了性能并确定这是一个问题

标签: java string algorithm


【解决方案1】:

这个函数应该覆盖它。每个 char 只检查一次,不会创建任何对象。

public static boolean validate(String token) {
  if (token == null || token.length() < 2) return false;
  if (!Character.isUpperCase(token.charAt(0)) return false;
  for (int i = 1; i < token.length(); i++)
    if (Character.isLowerCase(token.charAt(i)) return true;
  return false;

【讨论】:

    【解决方案2】:

    第一个条件就是length - 此数据缓存在字符串对象中,不需要遍历字符串。

    您可以使用Character.isUpperCase() 来确定第一个字符是否为大写。也不需要遍历字符串。

    最后一个条件需要对字符串进行一次遍历,并在您第一次找到小写字符时停止。


    附:组合 2+3 标准的另一种方法是使用 regex(不是更高效 - 但更优雅):

    return token.matches("[A-Z].*[a-z].*");
    

    正则表达式正在检查字符串是否以大写字母开头,然后是任何包含至少一个小写字符的序列。

    【讨论】:

      【解决方案3】:
      • 长度至少为 2 个字符
      • 第一个字符是 大写的
      • 第一个字符之后的剩余子字符串包含 至少 1 个小写字符

      代码:

      private boolean isInProperForm(final String token) {
          if(token.length() < 2) return false;
          if(!Character.isUpperCase(token.charAt(0)) return false;
          for(int i = 1; i < token.length(); i++) {
              if(Character.isLowerCase(token.charAt(i)) {
                  return true; // our last criteria, so we are free 
                               // to return on a met condition
              }
          }
          return false; // didn't meet the last criteria, so we return false
      }
      

      如果您添加了更多条件,则必须修改最后一个条件。

      【讨论】:

        【解决方案4】:

        怎么样:

        return token.matches("[A-Z].*[a-z].*");
        

        这个正则表达式以一个大写字母开头,后面至少有一个小写字母,因此符合您的要求。

        【讨论】:

        • 另一个要求是效率,所以我稍微修改一下:return token.matches("[A-Z].*?[a-z].*?");插入问号
        • 请注意,在正则表达式中,插入符号 ^ 在字符类之外是 not 否定。这是一个零宽度断言,表示字符串的开头。
        【解决方案5】:

        查找第一个字符是否为大写:

        Character.isUpperCase(token.charAt(0))
        

        检查是否至少有一个小写:

        if(Pattern.compile("[a-z]").matcher(token).find()) {
            //At least one lowercase
        }
        

        【讨论】:

          【解决方案6】:

          要检查第一个字符是否为大写,您可以使用:

          Character.isUpperCase(s.charAt(0))
          

          【讨论】:

            【解决方案7】:

            return token.matches("[A-Z].[a-z].");

            【讨论】:

            • 已经有两个答案给出了正则表达式,它们的格式比这更好。您还需要 * 在 . 之后
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多